Jak korzystac z repozytorium w kontrolerze

0

Czytam kolejna książkę o ASP NET MVC5 i po raz kolejny jest przykład ze pobieranie danych odbywa się w kontrolerze. Przewija sie to w wielu ksiazkach i tutorialach, mamy np:

 public class StudentController : Controller
    {
      private readonly IStudentRepository repository;

        public StudentController(IStudentRepository repo)
        {
            repository = repo;
        }
public ViewResult Edit(int id)
      
 {
            Student student = repository.Students.FirstOrDefault(s => s.StudentId == id);
            return View(student);
        }

//...
}

To jest bardzo prosty przykład, ale jak to będzie wygladało jak bedziemy chcieli pobrac i zwrocic dane z wielu repozytoriów, bedzie totalny chaos. Sadze ze nie tak powinno to wygladac. Według mnie powinien tam byc przekazywany ViewModel czyli ja bym to zrobil tak:

 public ViewResult Edit(int id)
        {
            StudentService studentService = new StudentService();
            StudentViewModel studentViewModel = studentService.GetStudentViewModel(id);
            return View(studentViewModel);
        }

Tylko w takim przypadku zastanawiam się jak z kontrolera (i czy w ogóle tak to zrobić) przekazywać repozytorium do studentService. Czy zrobić po prostu

public class StudentService
    {
        public StudentViewModel GetStudentViewModel(IStudentRepository repository, int id)
        {
            //pobieranie danych
            //mapowanie na StudentViewModel
            //zwracanie StudentViewModel
        }


        //...
    }

Tylko wtedy pojawia się problem bo StudentViewModel może mieć tez elementy z innych repozytoriów (ITeachersRepository, ILectureRepository)

Jak to ładnie ugryźć?

1

Wywal to reposytorium i korzystaj bezpośrednio z Dbcontextu . Ja odkąd robię w asp mvc jeszcze nigdy nie używałem repo, Moim zdaniem jest nie potrzebne

0

@szydlak: a mógłbyś pokazać jak to by wyglądalo poprawnie na moim przykładzie? DbContext powinien być przekazywany z kontrolera do StudentService?

3

Dbcontext i serwisy powinny być wstrzykiwane. Serwis do kontrolera a context do serwisu. Autofac ci w tym pomoże

3

@goodfather: Gratuluję. Zrozumiałeś coś, co wielu osobom sprawia trudność.
Jeszcze tylko mentalnie się odklej od tezy, że kontroler ma cokolwiek wspólnego z bazą danych.
W prostym przypadku ma być jak u Ciebie. Kontroler wywołuje jakieś metody serwisu i to serwis ma dostęp do bazy danych (zwykle wystarcza DBContext, bez jakichś niepotrzebnych warstw pośrednich, nazywanych często repozytorium).

Do zastanowienia czy viewmodel dla edycji to jest ten sam co do wyświetlenia. Może się okazać, że formularz edycji musie zawierać nieco inne dane niż wyświetlenie danych studenta i wtedy przydałby się osobny viewmodel dla edycji i w serwisie sobie to przetwarzasz.

W książkach o MVC tak piszą bo to nie książki o architekturze aplikacji tylko o frameworku MVC.

0

@szydlak: @jacek.placek a jeszcze takie pytanie. Mam model Student

public class Student
    {
        public int StudentId { get; set; }
        public string Name { get; set; }
        public string LastName { get; set; }
        public DateTime DateOfBirth { get; set; }
        //...
    }

chcę wyświetlić teraz dane tego studenta zeby uzytkownik mogl je edytowac. Tworze sobie wiec ViewModel

public class StudentViewModel
    {
        public int StudentId { get; set; }  //powinno tu byc czy nie?
        public string Name { get; set; }
        public string LastName { get; set; }
        public DateTime DateOfBirth { get; set; }
        //...
    }

Teraz pytania:

  1. czy w ViewModelu powinno sie znaleźć StudentId (sądze ze gdy jest to klucz z bazy to nie powinno a jesli to np numer indeksu studenta to powinno. Wiec nawet jak uzywam numeru indeksu jako klucza w tabeli to dałbym go do Viewmodelu.)
  2. gdzie wstawiac DataAnnotations? W modelu czy w viewmodelu?
1
  1. Tak. Dla udaru będzie konieczne. Dla insert nie przeszkadza.

  2. Dla viewmodel jeśli to adnotacje związane np. z walidacja, etykietą itp. Q modelu jeśli to adnotacje związane ze schematem db ale tu polecam FluentAPI.

0

Napisałem takie klasy (odzwierciedlaja one tabele jakie mam w bazie) czy poprawnie to wygląda, głównie chodzi mi o to ze w tym przypadku chce edytować studenta, ale chcialbym tez miec możliwość zmiany pokoju i biurka przypisanego do tego studneta, ewentualnie jesli wczesniej nie było takiego pokoju lub biurka to zeby został zrobiony odpowiedni insert do tabel Room i Desk. Chodzi mi tez o zasadnosc przekazywania RoomId i DeskId do viewmodelu.

public class Student
    {
        public int StudnetId { get; set; }
        public string Name { get; set; }
        public string Lastname { get; set; }
        public DateTime DateOfBirth{ get; set; }

        public int RoomId { get; set; }
        public int DeskId { get; set; }
    }

    public class Room
    {

        public int RoomId { get; set; }
        public int Number { get; set; }
        public string Description { get; set; }
        public int Capacity { get; set; }
    }

    public class Desk
    {
        public int DeskId { get; set; }
        public string Description { get; set; }
    }

//viewmodel przekazywany do widoku edycji studenta
    public class StudentEditViewModel
    {
        public int StudnetId { get; set; }
        public string Name { get; set; }
        public string Lastname { get; set; }
        public DateTime DateOfBirth { get; set; }
        public int RoomId { get; set; }
        public int RoomNumber { get; set; }
        public string RoomDescription { get; set; }
        public int RoomCapacity { get; set; }
        public int DeskId { get; set; }
        public string DeskDescription { get; set; }
    }

Czy nawet jeśli przekazuje pola Id do widoku, to powinienem je jakos ukrywać?

0

Dodaj sobie do Studenta public Room Room {get;set;} i public Desk Desk {get;set;}.
Jeśli przekazujesz do widoku ID studenta to dajesz to np do ukrytego inputa

0

Jak to w końcu jest z jechaniem na czystym contexcie? (@Aventus)

1

Odpowiedz jest prosta- to zalezy ;) Jesli piszemy zwyklego CRUDa to dla czego by nie uzywac bezposrednio contextu (chociaz nie w kontrolerach, o tym za chwile). Natomiast przy bardziej rozbudowanych aplikacjach moim zdaniem nie ma nic zlego w stosowaniu repozytoriow (czy jakkolwiek to nazwac, moze byc store/MyUnicornStorage/cokolwiek), a wrecz przeciwnie. Pomijajac juz fakt ze pozwala to calkowicie oddzielic warstwe infrastruktury od domeny (EF to tez swojego rodzaju taka warstwa, a raczej cos pomiedzy), taka abstrakcja ulatwia wyrazne kontrolowanie tego co i jak jest modyfikowane oraz wyciagane z bazy danych.

Co do samego uzywania repozytoriow czy tez contextu w kontrolerach, jest to moim zdaniem bledne. Kontrolery powinny byc "glupie" i jedynie przekazywac polecania- albo za pomoca serwisow albo przy zastosowaniu podejscia command-handler (MediatR). Jesli mamy do wyciagniecia bardziej skomplikowany model- tak jak opisane w tym watku- to mozemy miec do tego oddzielna metode w naszym repozytorium. Podsuwa to kwestie tego czy ogolne podejscie do problemu jest wlasciwe. Moze nalezalo by miec oddzielny modul odpowiedzialny za budowanie modelu widoku? Np. repozytorium wyciagajace dane z tabeli ktora jest niczym innym jak view modelem, zbudowanym ze zmian dokonanych do wielu encji w systemie. Cos takiego mozna osiagnac przy zastosowaniu eventow (lub np. notifications w MediatR). Za kazdym razem gdy dochodzi do interesujacej nas zmiany, w system zostaje wyslany event ktorych moze byc przetworzony przez dowolna liczbe subskrybentow. Takim subskrybentem moze byc wlasnie modul odpowiedzialny za budowanie (i posrednio za zapisywanie do bazy) widoku.

0

repozytorium wyciagajace dane z tabeli ktora jest niczym innym jak view modelem, zbudowanym ze zmian dokonanych do wielu encji w systemie.

Niemasz pojęcia czym są Repozytoria ani ViewModele skoro piszesz takie głupoty.

2
goodfather napisał(a):

Tylko wtedy pojawia się problem bo StudentViewModel może mieć tez elementy z innych repozytoriów (ITeachersRepository, ILectureRepository)

Jak to ładnie ugryźć?

Nie robić jakichś bzdurnych DAO dla każdej tabeli i nie nazywać ich "repozytoriami". Potrzebujesz wyświetlić gdzieś jakiś XViewModel, to napisz sobie klasę XViewModelProvider, wstrzyknij do niej DbContext. W jakiejś jedynej publicznej metodzie tej klasy zrób pobieranie danych z tylu tabel ile potrzebujesz, nie czytaj całych obiektów, tylko te kolumny, które mają sens dla danego widoku. (Czyli po prostu zrób odpowiednią projekcję.)
XViewModelProvider z kolei wstrzyknij do kontrolera, i niech on w swojej akcji wywołuję metodę providera.

Repozytoria nie mają nic wspólnego z żadnymi viewmodelami, ten wzorzec jest elementem DDD i co do zasady stanowi kolekcję aggregate rootów. Jeśli ktoś nazywa swoją warstwę dostępu do danych "repozytoriami", to trochę tak jakby nazywał swojego dwudziestoletniego fiata promem kosmicznym. Niby można tak robić, ale w oczach niektórych można się w ten sposób ośmieszyć. Wszak jedyne co tam jest kosmicznego, to problemy z korozją.

0

Nie robić jakichś bzdurnych DAO dla każdej tabeli i nie nazywać ich "repozytoriami". Potrzebujesz wyświetlić gdzieś jakiś XViewModel, to napisz sobie klasę XViewModelProvider, wstrzyknij do niej DbContext. W jakiejś jedynej publicznej metodzie tej klasy zrób pobieranie danych z tylu tabel ile potrzebujesz, nie czytaj całych obiektów, tylko te kolumny, które mają sens dla danego widoku. (Czyli po prostu zrób odpowiednią projekcję.)
XViewModelProvider z kolei wstrzyknij do kontrolera, i niech on w swojej akcji wywołuję metodę providera.

No ale to bez sensu, bo byś musiał odwrócić zależności względem warstwy View albo umieścić te ViewModele w jakiejś warstwie pośredniej.
Ponad to:

Jeśli potrzebujesz wyświetlić listę produktów w widoku to nie znaczy, że potrzebujesz ViewModelu.
ViewModel to po prostu "lepsza wersja ViewBag" która jest tworzona po to, żeby coś dodać co wynika bezpośrednio z mechaniki Widoku a nie tabeli w bazie.
ViewModel jest ci potrzebny np. przy formularzu lub gdy chcesz dodać jakieś linki dla produktu.
Nigdy nie zrozumiem myślenia w stylu warstwa prezentacji powinna być niezależna od warstw niżej, czego efektem jest robienie do wszystkiego "ViewModelu".
Przecież te warstwy niższego rzędu to fundament dla warstwy prezentacji.
Architektura Port Adapter w fajny sposób to ilustruje.

ten wzorzec jest elementem DDD i co do zasady stanowi kolekcję aggregate rootów.

Domyślam się, że chodzi o różne egzemplarze jednego Agregatu.

11
Opętany_Władca_Trolli napisał(a):

No ale to bez sensu, bo byś musiał odwrócić zależności względem warstwy View albo umieścić te ViewModele w jakiejś warstwie pośredniej.

To ja może narysuję, żeby było łatwiej zrozumieć ideę:

screenshot-20190114115827.png

Jeśli potrzebujesz wyświetlić listę produktów w widoku to nie znaczy, że potrzebujesz ViewModelu.
ViewModel to po prostu "lepsza wersja ViewBag" która jest tworzona po to, żeby coś dodać co wynika bezpośrednio z mechaniki Widoku a nie tabeli w bazie.

ViewModel to dane, które trzeba wyświetlić na widoku oraz metadane jeśli potrzebne. Bazy i żadnych tabel może w ogóle nie być.

Nigdy nie zrozumiem myślenia w stylu warstwa prezentacji powinna być niezależna od warstw niżej, czego efektem jest robienie do wszystkiego "ViewModelu".

No to i SRP też nigdy nie zrozumiesz.

Przecież te warstwy niższego rzędu to fundament dla warstwy prezentacji.

A na którym bootcampie tak mówia?

1

Człowieku, próbujemy Ci pokazać błędy w myśleniu, a Ty zamiast się zastanowić, to brniesz w to dalej.
Zawsze możesz też zrobić coś takiego w kontrolerze:

MySuperView view = new MySuperView();
view.AddStringParam("Imię klyenta", data.ClientName);
view.AddIntParam("Wiek klyenta", data.ClientAge);
view.AddBoolParam("Czy ma lewą nóżkę bardziej", data.ClientLeftLeg > data.ClientRightLeg);

return view;

I nikt Ci tego nie zabroni. Ale możesz też zrobić to NORMALNIE:

  
  return new MySuperView(dataProvider.GetData());

0
somekind napisał(a):

Potrzebujesz wyświetlić gdzieś jakiś XViewModel, to napisz sobie klasę XViewModelProvider, wstrzyknij do niej DbContext. W jakiejś jedynej publicznej metodzie tej klasy zrób pobieranie danych z tylu tabel ile potrzebujesz, nie czytaj całych obiektów, tylko te kolumny, które mają sens dla danego widoku. (Czyli po prostu zrób odpowiednią projekcję.)

1 sprawa
Dobrze. A w jaki sposob to testowac? Jak mockowac? Mockowanie "repozytoriów" w testach to było coś takiego

Mock<IStudentRepository> mock;

Czy jak korzystał bezpo średnio z DbContextu to mam sobie po prostu mockowac DbContext?

Mock<DbContext> mock = new Mock<DbContext>();

2 sprawa
I jeszcze drugie pytanie. Jak wstrzyknac DbContext uzywajac Ninjecta? Musze zrobić jakiś interfejs, np IStudentDbContext?

3 sprawa
@somekind powinienem miec cos takiego? Jak tu wstrzyknac DbContext skoro w kontrolerze nie ma dostępu doDbContext?

    public class StudentViewModelProvider
    {
        DbContext context;
        public StudentViewModelProvider(DbContext con)
        {
            context = con;
        }

        public StudentEditViewModel GetStudentsViewModel(int id)
        {
            // tutaj ląduje LINQ do wyciagniecia danych z 3 tabel.
            // mapowanie 3 obiektow do jednego StudentEditViewModel
            // Jescze nie wiem jak to zrobic ale się dowiem
        }
    }

    public ViewResult Edit(int id)
    {
        StudentViewModelProvider studentsProvider = new StudentViewModelProvider(); // jak tu wstrzyknac DbContext?
        StudentEditViewModel model = studentsProvider.GetStudentsViewModel(id);
        return View(model);
    }
0
goodfather napisał(a):

1 sprawa
Dobrze. A w jaki sposob to testowac? Jak mockowac? Mockowanie "repozytoriów" w testach to było coś takiego

A w jakim celu chcesz mockować? Co Ci da unit test klasy, której jedynym celem jest pobrać dane z bazy?
Moim zdaniem, jeśli chcesz testować automatycznie, to tylko integracyjnie, czyli wczytać faktyczne dane z bazy.

Czy jak korzystał bezpo średnio z DbContextu to mam sobie po prostu mockowac DbContext?

Mock<DbContext> mock = new Mock<DbContext>();

No na upartego, to chyba też można, bo metody są wirtualne. Nie wiem, nigdy tego nie robiłem, staram się unikać tego typu sytuacji.

2 sprawa
I jeszcze drugie pytanie. Jak wstrzyknac DbContext uzywajac Ninjecta? Musze zrobić jakiś interfejs, np IStudentDbContext?

Wstrzyknij DbContext, bez żadnych interfejsów.

3 sprawa
@somekind powinienem miec cos takiego? Jak tu wstrzyknac DbContext skoro w kontrolerze nie ma dostępu doDbContext?

Po prostu tak:

public class StudentViewModelProvider
{
    DbContext context;
    public StudentViewModelProvider(DbContext con)
    {
        context = con;
    }

    public StudentEditViewModel GetStudentsViewModel(int id)
    {
        // tutaj ląduje LINQ do wyciagniecia danych z 3 tabel.
        // mapowanie 3 obiektow do jednego StudentEditViewModel
        // Jescze nie wiem jak to zrobic ale się dowiem
    }
}

public class StudentsControler
{
    StudentViewModelProvider studentViewModelProvider;

    public StudentsControler(StudentViewModelProvider provider)
    {
        studentViewModelProvider = provider;
    }

    public ViewResult Edit(int id)
    {
        StudentEditViewModel model = studentViewModelProvider .GetStudentsViewModel(id);
        return View(model);
    }
}
0

@somekind:

Przecież ty nie odróżniasz zwykłego pojemnik na zdenormalizowaną projekcje z bazy danych od ViewModelu.
Ani nie masz pojęcia czym jest SRP.

I Jak pisałem wcześniej tworzeniem ViewModeli nie może zajmować się warstwa Domeny czy Aplikacji, a tworzeniem projekcji z bazy danych nie może zajmować się warstwa Prezentacji.

1

@goodfather: Nie mockuj DbContextu, to nie ma najmniejszego sensu. To jest właśnie jeden z problemów z nieodpowiednią architekturą, że zachodzi potrzeba mockowania DbContextu. Masz mockować serwis dający Ci dane. Czyli np: StudentProvider. Twoja prawdziwa wersja interfejsu IStudentProvider będzie używała DbContextu do zwrócenia danych. Ale zmockowana wersja ma po prostu zwrócić jakieś przykładowe dane i tyle.

0
Juhas napisał(a):

@goodfather: Nie mockuj DbContextu, to nie ma najmniejszego sensu. To jest właśnie jeden z problemów z nieodpowiednią architekturą, że zachodzi potrzeba mockowania DbContextu. Masz mockować serwis dający Ci dane. Czyli np: StudentProvider. Twoja prawdziwa wersja interfejsu IStudentProvider będzie używała DbContextu do zwrócenia danych. Ale zmockowana wersja ma po prostu zwrócić jakieś przykładowe dane i tyle.

Jeśli mówisz nie mockuj DbContextu tzn nie rób w ten sposób ?
https://docs.microsoft.com/pl-pl/ef/ef6/fundamentals/testing/mocking

2
sss napisał(a):

@somekind:

Przecież ty nie odróżniasz zwykłego pojemnik na zdenormalizowaną projekcje z bazy danych od ViewModelu.

ViewModel to wszystko, co potrzebne do wyświetlenia widoku. Może to być zarówno tylko projekcja danych z domeny, dodatkowe wyliczane wartości w locie, a także inne dane, które mogą być związane z konkretną technologią widoku. Może też byc kompozycją różnych obiektów, np. w przypadku formularza edycji zawierającego listy wyboru, wtedy nie będzie nawet płaski.

Ani nie masz pojęcia czym jest SRP.

A co konkretnie jest niezgodne z SRP w podejściu, w którym każdy widok ma swój viewmodel, a każdy z tych viewmodeli klasę tworząca go na podstawie danych z domeny?

I Jak pisałem wcześniej tworzeniem ViewModeli nie może zajmować się warstwa Domeny czy Aplikacji, a tworzeniem projekcji z bazy danych nie może zajmować się warstwa Prezentacji.

Formalnie masz rację. Można zawsze z DataAccess przesłać do BLL jakieś PersisetnceModele, tam zmapować je na DomainModele, potem przesłać DTO do GUI, a w GUI zmapować te DTO na ViewModele. Wtedy wszystko będzie ksiażkowo i zgodnie ze wszystkimi oficjalnymi definicjami z czerwonej/niebieskiej/zielonej/żółtej czy jakiejś tam innej książki.

Dla mnie jednak viewmodel to klasa, która trafia na ekran użytkownika, niezależnie od tego, czy przechodzi najpierw przez wszystkie 15 oficjalnych warstw, czy z jednego prostego źródła projekcji. Jasne, mógłbym sobie takie DTO pochodzące z wewnątrz zmapować na ViewModel w warstwie prezentacji i mieć prawilnie. Ale jakoś nie widzę żadnego zysku z takiego podejścia.

Czemu zamiast się mnie czepiać, nie zaproponujesz po prostu lepszego rozwiązania?

Juhas napisał(a):

@goodfather: Nie mockuj DbContextu, to nie ma najmniejszego sensu. To jest właśnie jeden z problemów z nieodpowiednią architekturą, że zachodzi potrzeba mockowania DbContextu. Masz mockować serwis dający Ci dane. Czyli np: StudentProvider. Twoja prawdziwa wersja interfejsu IStudentProvider będzie używała DbContextu do zwrócenia danych. Ale zmockowana wersja ma po prostu zwrócić jakieś przykładowe dane i tyle.

A po co interfejs do StudentProvider? W jakich testach mu się on przyda, skoro ta klasa ma być używana tylko w kontrolerze, a tych nie ma sensu testować?

0

ViewModel to wszystko, co potrzebne do wyświetlenia widoku. Może to być zarówno tylko projekcja danych z domeny, dodatkowe wyliczane wartości w locie, a także inne dane, które mogą być związane z konkretną technologią widoku. Może też byc kompozycją różnych obiektów, np. w przypadku formularza edycji zawierającego listy wyboru, wtedy nie będzie nawet płaski.

"Tylko projekcja danych z domeny" to nie jest ViewModel. Równie dobrze możesz nazwać wszystko ViewModelem - DTO, PrezentationModel, DomainModel, no bo przecież najlepiej wsadzić wszystko do jednego worka to takie zgodne z SRP.

A co konkretnie jest niezgodne z SRP w podejściu, w którym każdy widok ma swój viewmodel, a każdy z tych viewmodeli klasę tworząca go na podstawie danych z domeny?

To że wycieka ci abstrakcja odpowiedzialna za budowanie Widoku do Warstwy Domenowej - Aplikacyjnej.

Formalnie masz rację. Można zawsze z DataAccess przesłać do BLL jakieś PersisetnceModele, tam zmapować je na DomainModele, potem przesłać DTO do GUI, a w GUI zmapować te DTO na ViewModele. Wtedy wszystko będzie ksiażkowo i zgodnie ze wszystkimi oficjalnymi definicjami z czerwonej/niebieskiej/zielonej/żółtej czy jakiejś tam innej książki.

Dla mnie jednak viewmodel to klasa, która trafia na ekran użytkownika, niezależnie od tego, czy przechodzi najpierw przez wszystkie 15 oficjalnych warstw, czy z jednego prostego źródła projekcji. Jasne, mógłbym sobie takie DTO pochodzące z wewnątrz zmapować na ViewModel w warstwie prezentacji i mieć prawilnie. Ale jakoś nie widzę żadnego zysku z takiego podejścia.

Czemu zamiast się mnie czepiać, nie zaproponujesz po prostu lepszego rozwiązania?

Widzę, że skończyły ci się argumenty, dlatego postanowiłeś je sobie wymyślić. Masz taką bogatą wyobraźnie...

1
sss napisał(a):

"Tylko projekcja danych z domeny" to nie jest ViewModel.

Jeśli użyta jako źrodło danych dla widoku to jest ViewModelem.

Równie dobrze możesz nazwać wszystko ViewModelem - DTO, PrezentationModel, DomainModel, no bo przecież najlepiej wsadzić wszystko do jednego worka to takie zgodne z SRP.

SRP to zasada dotycząca organizacji kodu, nie ma nic wspólnego z nazewnictwem poszczególnych kategorii obiektów. Nie można złamać SRP nazywając coś źle.

To że wycieka ci abstrakcja odpowiedzialna za budowanie Widoku do Warstwy Domenowej - Aplikacyjnej.

Nic nie wycieka, bo zwracane są same dane, nic związanego z technologią widoku.

Widzę, że skończyły ci się argumenty, dlatego postanowiłeś je sobie wymyślić. Masz taką bogatą wyobraźnie...

Znowu to samo - narzekasz, piszesz, że nie tak powinno byc, i że wszystko źle, ale nie jesteś w stanie niczego konkretnego zapropnować w zamian. Bardzo jesteś pomocny. :)

0
sss napisał(a):

A co konkretnie jest niezgodne z SRP w podejściu, w którym każdy widok ma swój viewmodel, a każdy z tych viewmodeli klasę tworząca go na podstawie danych z domeny?

To że wycieka ci abstrakcja odpowiedzialna za budowanie Widoku do Warstwy Domenowej - Aplikacyjnej.

Możesz rozwinąć co rozumiesz przez powyższe? I może napisz parę słów o tym jak wymieniasz między warstwami dane?

0

Nic nie wycieka, bo zwracane są same dane, nic związanego z technologią widoku.

Teoretycznie, można coś takiego zrobić ale byś musiał mieć jakąś warstwę pośrednią jak knotrakt z SOA.

Ale to i tak bez sensu bo jak zbudujesz ViewModel, który będzie zawierał takie detale jak paginację z linkami.? To już wychodzi po za zakres aplikacji, domeny.

Poza tym dla mnie ViewModel to coś co posiada jakąś ekstra logikę lub metadane związane z technologią jak np. RestModel, ViewModel etc. Jeśli jest to zwykła projekcja z schematu bazy to powinno się używać jakiejś ogólnej nazwy a nie nazwy związanej z "rodzajem" prezentacją.

1
sss napisał(a):

Jeśli jest to zwykła projekcja z schematu bazy to powinno się używać jakiejś ogólnej nazwy a nie nazwy związanej z "rodzajem" prezentacją.

Dobrze, można używac nazwy ogólniej. Można to sobie nazwać DTO, albo ReadModelem, albo w zależności od zastosowania: ListModelem, DetailsModelem. Więcej pomysłów nie mam.

0
somekind napisał(a):
goodfather napisał(a):

Tylko wtedy pojawia się problem bo StudentViewModel może mieć tez elementy z innych repozytoriów (ITeachersRepository, ILectureRepository)

Jak to ładnie ugryźć?

Nie robić jakichś bzdurnych DAO dla każdej tabeli i nie nazywać ich "repozytoriami". Potrzebujesz wyświetlić gdzieś jakiś XViewModel, to napisz sobie klasę XViewModelProvider, wstrzyknij do niej DbContext. W jakiejś jedynej publicznej metodzie tej klasy zrób pobieranie danych z tylu tabel ile potrzebujesz, nie czytaj całych obiektów, tylko te kolumny, które mają sens dla danego widoku. (Czyli po prostu zrób odpowiednią projekcję.)
XViewModelProvider z kolei wstrzyknij do kontrolera, i niech on w swojej akcji wywołuję metodę providera.

Podoba mi się takie podejście, ale co jeśli sprawę utrudnia DMZ. U mnie w firmie, aplikacja nie ma bezpośredniego dostępu do danych i wszystko idzie po WCF (dedykowanym dla tej aplikacji). W takim razie powinienem mapować DTO na ViewModele, czy może web service powinien zwracać gotowy ViewModel?

1

Ja pisałem o tym jak to zorganizować w jednej aplikacji. Ty masz dwie aplikacje, więc siłą rzeczy tego nie zrealizujesz. WCF niech nie zwraca żadnych viewmodeli, to by było zupełnie bez sensu.

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