2013-01-15 9 views
46

Właśnie zacząłem pracować ze strukturą Entity i jestem zdezorientowany tym, w jaki sposób klasy w warstwie biznesowej pasują do jednostek tworzonych przez Entity Framework .Nieporozumienia związane z logiką biznesową podczas korzystania z architektury Entity

Podczas pracy z klasycznym ADO.NET, mam klasę o nazwie Klient na przykład, a następnie inną klasę o nazwie DALCustomer do obsługi interakcji z bazą danych, w tej strukturze wstawiłbym kod do wykonywania obliczeń, filtrowania i usuwania instancji DAL z Klientem do zapisywania, aktualizacji i usuwania w klasie Klienta.

W przypadku Entity Framework, jeśli masz tabelę o nazwie Customer, struktura Entity tworzy encję o nazwie Customer i to tam zaczyna się moje zamieszanie, czy ta jednostka usuwa potrzebę Klienta w warstwie biznesowej? Więc w istocie wszystkie pola i metody, które normalnie wchodzą w warstwę biznesową, przechodzą w jednostkę wygenerowaną przez Entity Framework? A może klasa nadal istnieje w warstwie biznesowej o nazwie CustomerBL na przykład, która wciąż zawiera pola i metody potrzebne do osiągnięcia logiki biznesowej wymaganej do obliczeń, filtrowania i nadal potrzebuje instancji EF DAL zadeklarowanej do obsługi dostępu do danych?

Jeśli istnieje klasa biznesowa, w tym przypadku CustomerBL, pojawia się jeszcze jedno pytanie, czy pola utworzone w jednostce klienta powinny zostać odtworzone w CustomerBL lub czy instancja jednostki Klienta powinna zostać zadeklarowana w CustomerBL więc nie byłoby potrzeby zadeklarowania pól w 2 lokalizacjach?

Odpowiedz

5

Nie wiem, czy to uważane za dobrą praktykę przez innych, ale osobiście to jest jak obchodzić to w przeszłości:

Klasy wygenerowane przez EF są Twoje DAL, a następnie przez BL stworzenia komplementarnego zestawu klas, w których będziesz mieć wymaganą strukturę (jak na przykład łączenie danych z powiązanych jednostek w relacji jeden do jednego) i inne problemy logiki biznesowej są obsługiwane (niestandardowe sprawdzanie poprawności, takie jak implementacja IDataErrorInfo, aby było dobrze odtwarzane z interfejsem w WPF dla wystąpienie), a także utworzyć klasy, które będą zawierać wszystkie metody warstw biznesowych odnoszące się do typu jednostki, które wykorzystują instancje BL i konwertują do obiektów typu "z" i na obiekty BL do obiektów BL.

Na przykład klient ma swoją bazę danych. EF wygeneruje klasę Klient, aw BL znajdzie się klasa Klient (prefiks, sufiks itp.) Oraz klasa CustomerLogic. W klasie klienta BL możesz robić wszystko, co jest potrzebne do spełnienia wymagań bez konieczności manipulacji z jednostkami EF, aw klasie CustomerLogic masz metody BL (załaduj najbardziej wartościowych klientów, zapisz klienta dodatkowymi danymi itp.).

Pozwala to na luźne powiązanie z implementacją źródła danych. Innym przykładem tego, co przyniosło mi korzyści w przeszłości (w projekcie WPF), jest to, że można zrobić rzeczy takie jak implementacja IDataErrorInfo i implementować logikę walidacji w klasach CustomerBL, tak aby po związaniu encji z formularzem tworzenia/edycji w interfejsie użytkownika skorzystasz z wbudowanej funkcjonalności zapewnionej przez WPF.

... Moje 2 centy, jestem również ciekawa, jakie są najlepsze praktyki lub jakie są inne rozwiązania/punkty widzenia.


także być może związane z tym tematem - Code-first vs Model/Database-first

+0

Jak obsługiwać pola, które są generowane przez EF i są potrzebne w klasie BL? Czy możesz podać trochę próbki swojej metody? –

+1

Cóż, brakuje tego, co napisałem, o tym, że potrzebujesz metod, które będą kopiować dane do/z obiektów BL/DAL, i oddzielasz się od DAL, implementując wzorzec repozytorium, abyś nie miał dostępu ObjectSets bezpośrednio, ale zamiast tego wywołujesz repozytoria dla operacji CRUD – dutzu

+0

Częściowe klasy to sposób na radzenie sobie z nimi. –

24

Entity Framework, w przeciwieństwie do LINQ-SQL na przykład, został zaprojektowany z oddzielenia modelu danych i modelu koncepcyjnego w umyśle.Obsługuje inheritance, , table splitting, complex types i transparent many-to-many associations, z których wszystkie umożliwiają formowanie modelu domeny do potrzeb użytkownika bez nadmiernego ograniczenia przez model magazynu danych.

Podejście pierwsze do kodu umożliwia pracę z obiektami POCO, w których wybrane właściwości można odwzorować na kolumny magazynu danych. Model-first i Database-first generują klasy cząstkowe, pozwalając na rozszerzenie wygenerowanego kodu. Praca z tymi zajęciami ma w dużej mierze wygląd i sposób pracy z POCO. Jeszcze więcej od wersji 5, kiedy DbContext stało się domyślnym API, więc wygenerowane klasy nie były już wypchane kodem trwałości związanym z API ObjectContext.

Oczywiście ten rozdział modelu koncepcyjnego i modelu sklepu może się tylko powieść w pewnym stopniu. Niektóre rzeczy działają przeciwko temu celowi: ignorancja uporu. Na przykład, jeśli pożądane jest leniwe ładowanie, konieczne jest zadeklarowanie właściwości nawigacyjnych jako virtual, więc EF może nadpisać je w typach proxy. A ponadto wygodne jest posiadanie prymitywnych właściwości klucza obcego (powiedzmy, ParentId) towarzyszących "prawdziwym" powiązaniom (odniesienie Parent). Puryści uważają to za pogwałcenie projektowania opartego na domenie.

Innym ważnym naruszeniem ignorancji wytrwałości jest duża liczba differences between linq-to-objects and linq-to-entities. Po prostu nie możesz zignorować faktu, że jesteś linq-ing na zupełnie innym wszechświecie niż obiekty w pamięci. Jest to nazywane tight coupling, or leaky abstraction.

Ale wtedy ... generalnie cieszę się z wykorzystywania wygenerowanych klas EF lub POCO z pierwszego modelu kodu jako klas domeny. Do tej pory nigdy nie widziałem bezkolizyjnego przejścia z jednego magazynu danych do innego, jeśli w ogóle się to zdarza. Niewiedza o niepoznawalności jest fikcją. Osobliwości z DAL zawsze pozostawiają ślad w domenie. Tylko wtedy, gdy trzeba kodować różne magazyny danych/modele lub gdy sklepy/modele mają się zmieniać stosunkowo często, opłaca się zminimalizować ten ślad w maksymalnym stopniu lub całkowicie go usunąć.

Innym czynnikiem jest to, że mogą promować klasy EF, ponieważ klasy domenowe są takie, że wiele aplikacji ma dziś wiele poziomów, gdzie (serializowane) różne modele widoku lub DTO są wysyłane do klienta. Używanie klas domen w UI prawie nigdy nie pasuje do rachunku. Równie dobrze możesz korzystać z klas EF jako domeny i mieć usługi wyrzucania dedykowanych modeli i DTO zgodnie z wymaganiami interfejsu użytkownika lub klientów usług. Kolejna warstwa abstrakcji może być większym ciężarem niż błogosławieństwem, jeśli tylko pod względem wydajności.

+0

Nie rozumiem, co masz na myśli mówiąc: "opiera się pokusie polegania na rzeczach, które EF wkłada tam, INotifyPropertyChanged'? Szablony t4 można zmodyfikować, aby zaimplementować takie rzeczy, jeśli to konieczne. –

+0

Oczywiście, mogą być modyfikowane. Mam na myśli to, że używanie tych generowanych przez EF właściwości i metod jeszcze bardziej zaciemnia niewiedzę o wytrwałości. Standardowe szablony mogą się zmieniać wraz z nowymi wersjami. –

+4

Gert, brak szacunku, ale mógłbyś dołączyć do mnie na moim poziomie i być może dać mi pojęcie, jak to, co mówisz, odnosi się do przykładu w moim oryginalnym wpisie, ponieważ nie jestem całkowicie za tobą, ponieważ jestem w końcu zupełnie nowy EF. –

13

Moim zdaniem, cały sens korzystania z POCO jako podmiotów, które można utrwalić, polega na usunięciu rozróżnienia między "jednostkami baz danych" i "podmiotami gospodarczymi". "Podmioty" mają być "podmiotami gospodarczymi", które można bezpośrednio utrwalać i ładować z magazynu danych, a tym samym działać jako "jednostki baz danych" w tym samym czasie. Korzystając z POCO, jednostki biznesowe są oddzielone od określonego mechanizmu, aby wejść w interakcję z bazą danych.

Możesz przenosić obiekty do osobnego projektu - na przykład - który nie ma żadnych odniesień do żadnego zespołu EF, a jednocześnie używa ich w projekcie warstwy bazy danych do zarządzania utrwalaniem.

Nie oznacza to, że można całkowicie zaprojektować swoje jednostki biznesowe, nie mając jednocześnie na uwadze wymagań dotyczących EF.Istnieją ograniczenia co trzeba wiedzieć, aby uniknąć kłopotów, gdy przyjdziesz do punktu mapować podmioty gospodarcze do schematu bazy danych za pomocą EF, na przykład:

  • należy dokonać właściwości nawigacyjnych (referencje lub kolekcji odniesień do innych podmiotów) virtual do obsługi leniwego ładowania za pomocą EF
  • Nie można użyć kolekcji IEnumerable<T> w przypadku kolekcji, które muszą być utrwalone. Musi to być ICollection<T> lub bardziej wyprowadzony typ.
  • Niełatwo utrzymują private właściwości
  • Typ char nie jest obsługiwane przez EF i nie można go używać, jeśli chcesz, aby utrzymywać jej wartości
  • i więcej ...

Ale dodatkowy zestaw podmiotów jest - moim zdaniem - dodatkową warstwą złożoności, która powinna być uzasadniona, aby była naprawdę potrzebna, jeśli wymienione ograniczenia są zbyt wąskie dla twojego projektu.

YA2C (Jeszcze kolejne 2 centów :))

+3

Zgadzam się z tym również, że to podstawowe mechanizmy ORM "zastępują" warstwę danych, a nie same podmioty. W aplikacji typu MVC mogę utworzyć osobne ViewModels w celu wyrażenia określonych informacji nie pochodzących od Entity, jeśli jest to wymagane. Podobnie jak w przypadku OP, choć czasami trudno jest mi nawigować. – Matthew

0

użyłem logikę biznesową napisać moje metody i powrót wyniki w jego utworzonym widoku, jak:

namespace Template.BusinessLogic 
{ 
    public interface IApplicantBusiness 
    { 
     List<Template.Model.ApplicantView> GetAllApplicants(); 

     void InsertApplicant(Template.Model.ApplicantView applicant); 
    } 
} 
Powiązane problemy