Odpowiadając na pytanie z tematu: repozytorium zwraca aggregate root'a, DAL zwraca coś, bo jest to tak szerokie pojęcie, że nie da się sprecyzować.
Obecnie najpraktyczniejszym rozwiązaniem wydaje mi się takie, gdzie:
- Kontroler pyta się serwisu o gotową
List<ViewModel>
, przekazuje ją do widoków.
- Serwis pyta się DAL o
IQueryable<Model>
, mapuje przez Select
na List<ViewModel>
i zwraca do kontrolera.
- DAL się pyta DB o
IQueryable<Model>
i takie zwraca do serwisu.
Czy coś byście tu zmienili?
Projekcję (użycie Select
) najlepiej robić tam, gdzie można zrobić to najefektywniej unikając ładowania zbędnych danych z bazy, a nie delegować do wyższych warstw. IQueryable
to jest szczegół implementacji ORMa, to też nie powinno trafiać do wyższych warstw. Po prostu jak już chcesz mieć oddzielną warstwę DAL, to niech ona się zajmuje danymi w pełni.
Sam bym zrobił tak, że kontroler pyta query handlera , a ten pobiera z ORMa dane zmapowane na ViewModel i zwraca do kontrolera. Nie widzę sensu w komplikowaniu dodatkowymi warstwami, które niczego nie wnoszą.
Pytasz się bazę bezpośrednio o obiekt domenowy? Powinieneś mieć jakieś encje ORM, czy tam POCOsy, które czytasz z bazy i z nich dopiero tworzyć obiekt domenowy.
No jak się ma sensownego ORMa, a nie z serii Lego Duplo, to oddzielne encje ORMa nie są POCO
tylko po co?
Zwłaszcza, że z tego, co rozumiem, to tutaj nie ma domeny, tu jest pobranie danych z bazy i wypchnięcie ich na GUI/API endpoint.
No jeśli ORM nie ma takich dziwny i nie wymaga takich pól, konstuktorów domyślnych itp i pola wymagane w obiekcie domenowym zgadzają się 1:1 to jednego to masz rację. Tylko że rzadko tak bywa w prawdziwym świecie ;)
Ale czemu ma się coś zgadzać 1:1? Domena jest jaka jest, a ORM mapuje ją jak wynika ze sposobu przechowywania danych przez bazę. Domeny nie interesuje jakie tabele ORM potworzy, czy np. ValueObject trafi do oddzielnej tabeli, czy będzie składowany w tej samej co encja, co będą zawierały tabele pośredniczące, itd.