Entity Framework i unikanie modelu domeny anemicznej

11

W naszej logice biznesowej czasami mamy zdefiniowane metody, takie jak to:

User.ResetCourse(Course courseToReset)

Problem polega na tym, że zarówno Użytkownik, jak i Kurs są obiektami proxy Entity Framework. Oznacza to, że kiedy trafimy na właściwości nawigacji użytkownika lub kursu, może to spowodować ogromne trafienie w bazie danych, ponieważ obiektów tych nie można poddać IQueryable, więc przechodzi przez nie normalnie.

Aby rozwiązać ten problem, zmieniliśmy podpis na:

User.ResetCourse(MyDBContext db, Course courseToReset)

Oznacza to, że możemy bezpośrednio zapytać bazę danych, aby wprowadzić potrzebne zmiany w efektywny sposób, ale przekazanie kontekstu bazy danych do obiektu biznesowego wydaje się tak błędne.

Później przenieśliśmy do użytkownika warstwę usługi, co oznacza, że ​​mamy coś takiego:

CourseService.ResetForUser(Course courseToReset, User forUser)

Ta usługa zawiera odniesienie do DBContext wprowadzonego podczas tworzenia, ale teraz nasze obiekty biznesowe są tylko workami danych bez zachowania (tj. Model domeny anemicznej).

Jak możemy tego uniknąć?

Steve
źródło
11
Brzmi to tak, jakbyś właśnie uświadomił sobie, że modele szkieletu encji to tak naprawdę DTO, a nie tak naprawdę model domeny. Czy faktycznie próbujesz zrobić DDD? Jeśli nie, prawdopodobnie nie ma to znaczenia.
Pan Cochese,
3
Usługi ADM plus to dobra architektura dla wielu rzeczy
Ewan
2
@JohnWu to bardzo stronniczy artykuł. Rzeczywiście zawiera wersję „Strawmana” bogatego modelu domeny, włączając wzorzec Active Record w bogatym przykładzie. Z pewnością Active Record nie jest zalecany w DDD i ogólnie jest złym wyborem dla każdej złożonej aplikacji.
RibaldEddie

Odpowiedzi:

8

Problem polega na tym, że używasz obiektów EF jako obiektów domeny. Obiekty EF są modelami danych, a NIE modelami biznesowymi.

Musisz zadeklarować obiekty biznesowe, które dają Ci swobodę robienia tego, czego potrzebujesz, a następnie pobrać je i przechowywać w repozytorium. Twoje repozytorium zamapuje podmioty EF na podmioty biznesowe. Obiekty EF nigdy nie powinny być używane poza twoimi repozytoriami.

TheCatWhisperer
źródło
0

Prawdopodobnie można tego uniknąć, wykonując coś takiego:

CourseService.prepareForUserCourseReset(DBContext db);
User.reset();
Course.reset();
CourseService.completeUserCourseReset(DBContext db);

Albo coś w tym rodzaju, jeśli złapiesz mój dryf. Wygląda na to, że podejście, które zastosowałeś w opisanym początkowym sposobie, jest związane z wydajnością i niekoniecznie związane ze strukturą domeny. Naprawdę powinieneś rozważyć rozwiązanie problemu z wydajnością w warstwie usług, ale możesz zachować zachowanie w domenie. Dobrze byłoby wiedzieć, co to znaczy zresetować użytkownika / kurs również w tym kontekście, jeśli chcesz uzyskać lepszą odpowiedź.

RibaldEddie
źródło