Wyszukanie rekordu w tabeli i przekazanie danych do widoku?

0

Witam

mam dwie tabele Artykul i ArtykulTresc
dodałem do projektu ArtykulViewModel i w nim

    public class ArtykulViewModel
    {
        public IEnumerable<Artykul> Artykul { get; set; }

        public IEnumerable<ArtykulTresc> ArtykulTresc { get; set; }
    }

w kontrolerze pobieram rekord z tabeli Artykul o przekazanym id oraz treść artykułu z tabeli ArtykulTresc
w var artykul i artykulTresc na końcu dodaję Single() i tu jest problem jak zmienię na ToList() jest ok

        public ActionResult Artykul(int id)
        {
            var artykul = db.Artykul.Include("ArtykulTresc").Where(a => a.ArtId == id).Single();
            var artykulTresc = artykul.ArtykulTresc.Single();

            var vm = new ArtykulViewModel
            {
                Artykul = artykul,
                
                ArtykulTresc = artykulTresc
            };

            return View(vm);
        }

Jak powinienem prawidłowo pobrać te dane z obu tabel i przekazać do widoku?
Czy w kontrolerze mogę dodawać jednocześnie using do Models i ViewModels?

Pozdrawiam

0
GAMMIS napisał(a):

w var artykul i artykulTresc na końcu dodaję Single() i tu jest problem

Ale jaki problem? Leci wyjątek? Nie ma danych? Komputer wybucha?

Zgaduje, że leci wyjątek bo masz więcej niż jeden element w kolekcji, a zgodnie z dokumentacją (warto czasem zajrzeć): " throws an exception if there is not exactly one element in the sequence". Zamist Single użyj FirstOrDefault, bo zgaduje, że chcesz pobrać tylko jeden, pierwszy element.

Jak powinienem prawidłowo pobrać te dane z obu tabel i przekazać do widoku?

Prawidłowo, to w jakiejś osobnej warstwie architektonicznej, a nie w kontrolerze, ale na razie bym się tym nie martwił i zostawił tak jak jest.

Czy w kontrolerze mogę dodawać jednocześnie using do Models i ViewModels?

Możesz, co nie znaczy, że powinieneś. Powinieneś mieć jakiś np. serwis, który będzie pobierał dane z bazy, mapował na view model i zwracał już gotowy do wyświetlenia obiekt, który w kontrolerze tylko przekażesz do widoku. Ale tym tez bym się na razie nie przejmował, bo podejrzewam, że dopiero zaczynasz.

0

Ok

Zrobiłem tak

W kontr. Artykul pobieram dane z tabeli Artykul i przekazyje je do widoku
następnie w tym widoku odwołuję się do PartialView

@Html.Action("_ArtTresc", Model.ArtId)

gdzie pobieram dane z tabeli ArtykulTresc i wyświetlam na tej stronie.

Działa ok tylko zastanawiam się czy to jest poprawne podejście do sprawy
czy może powinienem to zrobić inaczej lepiej bezpieczniej itp.

Dzięki za wyrozumiałość.

0

A dlaczego masz 2 tabele? Jest jakiś powód? Nawet jesli tak, to kontroler mógłby dostać 1 obiekt (viewmodel) z treścią i wyslac do widoku.

0
jacek.placek napisał(a):

A dlaczego masz 2 tabele? Jest jakiś powód? Nawet jesli tak, to kontroler mógłby dostać 1 obiekt (viewmodel) z treścią i wyslac do widoku.

  1. A dlaczego masz 2 tabele? Jest jakiś powód?

Zakładam że treść artykułu może ulec zmianie
w takim wypadku stara wersja artykułu ma być zachowywana bez zmian a zmodyfikowany artykuł tworzony jako nowy rekord z aktualną datą modyfikacji.

  1. Nawet jesli tak, to kontroler mógłby dostać 1 obiekt (viewmodel) z treścią i wyslac do widoku.

Utworzyłem ViewModel:

    public class ArtykulViewModel
    {
        public IEnumerable<Artykul> Artykul { get; set; }

        public IEnumerable<ArtykulTresc> ArtykulTresc { get; set; }
    }

i do widoku przekazuję na podstawie otrzymanego Id artykułu konkretny Artykuł ( Temat, autora, datę publikacji itp. )

        public ActionResult Artykul(int id)
        {
            var artykul = db.Artykul.Include("ArtykulTresc").Where(a => a.ArtId == id).Single();

oraz treść artykułu

            var artykulTresc = artykul.ArtykulTresc.Single();

do widoku przekazuję viewmodel vm

            var vm = new ArtykulViewModel
            {
                Artykul = artykul,

                ArtykulTresc = artykulTresc
            };

            return View(vm);
        }

Problem jest taki że jak na końcu zapytania do bazy dam .Single()
to nie mogę wykonać przepisania danych

                Artykul = artykul,
                ArtykulTresc = artykulTresc

jak Single() zamienię na ToList() jest OK.

ale w widoku muszę robić pętlę :(
tylko po co jeśli w wyniku mam tylko jeden rekord z tabeli Artykul i jeśli poprawię zapytanie do tabeli ArtykulTresc i pobiorę tylko ostatnią wersję treści to też otrzymam jeden rekord.

I tu coś mi nie pasuje. Wydaje mi się że popełniam jakiś błąd.

1

A ok. Tylko viewmodel to nie jest to co zrobiłeś bo teraz masz obiekt zawierający kolekcje obiektów artykuł i listy obiektów treść.
A chyba powinien być jeden artykuł i jedna treść. Poza tym to nie jest viewmodel tylko cos w rodzaju fasady opakowujacej artykuł i treść.
Viewmodel powinien zawierać dane z obu klas ( tytuł, treść i co tam jeszcze masz w tych klasach). Pisze z telefonu więc będzie brzydko.
Np
Klasa ArtykulViewModel
{
string tytul...;
strimg treść...;
}

i przy pobraniu z bazy artykułu i i treści w jakimś serwisie czy repozytorium zwracasz utworzony i wypełniony obiekt ArrykulViewModel tylko z danymi a nie z obiektami Artykuł i Treść. Chodzi o to,żeby widok nie musiał wiedzieć, że jest osobno treść a osobno artykuł.

A jak masz nową wersję to tytuł się nie zmienia?

0

Zakładam że tytuł nie ulega zmianie, tylko treść i data ostatniej modyfikacji.

1
public class ArtykulViewModel
{
    public int ArtukulId {get;set;}
    public int TrescId {get;set;}

    public string Tytul {get;set;}
    public string Tresc {get;set;}
// i co tam jeszcze chcesz, data publikacji, autor itd
}

 public ActionResult Artykul(int id)
        {
            var artykul = db.Artykul.Include("ArtykulTresc").Where(a => a.ArtId == id).FirstOrDefault(); // albo Find(id) zamiast Where...
            if(artykul == null)
                return View();

            var artykulTresc = artykul.ArtykulTresc.FirstOrDefault(x=>x.CurrentVersion == true); // jeśli masz jakąś flagę bieżącej wersji
            if(artykulTresc == null)
                return View();

            var vm = new ArtykulViewModel
            {
                ArtykulId =  = artykul.Id,
                TrescId =  = artykulTresc .Id,

                Tytul = artykul.tutul;
                ArtykulTresc = artykulTresc.Tresc;
            };

            return View(vm);
        }

wtedy w widoku masz czysty obiekt i nie trzeba nic iterować.

0

Serdeczne dzięki za cenną pomoc.
Pozdrawiam

1 użytkowników online, w tym zalogowanych: 0, gości: 1