Entity Framework i separacja warstw

12

Próbuję trochę popracować z Entity Framework i mam pytanie dotyczące rozdzielania warstw.

Zwykle używam interfejsu UI -> BLL -> DAL i zastanawiam się, jak tutaj używać EF.

Mój DAL zwykle byłby podobny

GetPerson(id)
{
    // some sql
    return new Person(...)
}

BLL:

GetPerson(id)
{
    Return personDL.GetPerson(id)
}

Interfejs użytkownika:

Person p = personBL.GetPerson(id)

Moje pytanie brzmi teraz: skoro EF tworzy mój model i DAL, czy dobrym pomysłem jest owinięcie EF w mój własny DAL, czy to tylko strata czasu?

Jeśli nie muszę owijać EF, czy nadal umieściłbym mój Model.esmx w swojej własnej bibliotece klas, czy też dobrze byłoby po prostu umieścić go w mojej BLL i tam pracować?

Naprawdę nie widzę powodu, aby umieścić EF w moim własnym DAL, ale chcę wiedzieć, co robią inni ludzie.

Zamiast mieć powyższe, pominąłbym DAL i po prostu zrobiłbym:

BLL:

GetPerson(id)
{
    using (TestEntities context = new TestEntities())
    {
            var result = from p in context.Persons.Where(p => p.Id = id)            
                    select p;
    }
}

Co robić?

Tomasz
źródło

Odpowiedzi:

13

Podany przykład to architektura mało warstwowa. Wiem, że celowo zostało uproszczone, ale:

Twoja warstwa prezentacji jest bezpośrednio powiązana z bytem Osoba. Jest to OK tylko w najprostszych przypadkach, a na pewno nie, gdy próbujesz zdefiniować swoje warstwy.

Metoda GetPerson wykorzystuje również dość złą praktykę tworzenia nowego kontekstu dla każdego połączenia. Powinieneś pobrać kontekst do konstruktora, a dostarczy go twój kontener IOC.

Prosta, ale skuteczna struktura, którą zastosowałem to:

  • Project.Core - zawiera modele widoków i interfejsy.
  • Project.DAL - z moim EDMX i wygenerowanym kodem.
  • Project.BLL - logika biznesowa.
  • Project.Web - sama aplikacja internetowa.

To ważne by zauważyć że:

  • Rdzeń nie jest zależny od żadnego innego rozwiązania.
  • DAL nie zależy od żadnego innego rozwiązania.
  • Project.Web zależy od rdzenia, ale nie od DAL ani BLL.
  • BLL zależy od rdzenia i DAL.
Borys Jankow
źródło
1
Rdzeń wydaje się być warstwą obiektów biznesowych.
sq33G
Tego właśnie używam, ale dodam dodatkowe biblioteki DLL, aby obsłużyć deklaracje interfejsu. W ten sposób odwołujesz się tylko do interfejsów (i używasz czegoś takiego jak [url = unity.codeplex.com/]Unity[/url] dla DI) i możesz być pewien, że nie ma żadnych dziwnych zależności, które przypadkowo wywołałeś.
Ed James
Zwykle bez EF tworzę własną klasę Person w warstwie „Model”, więc mam interfejs użytkownika, BLL, DAL i model, w którym: interfejs użytkownika zna BLL i model. BLL zna DAL i model. DLL zna model. Czy tworzysz także własne „modele widoków” i dlaczego nie używasz tylko generatorów EF? (wiem, że jest to sprzeczne z architekturą warstwową, ale ile razy faktycznie zmieniasz sposób uzyskiwania danych?)
Thomas
@Thomas zawijanie modeli widoku w coś abstrakcyjnego znacznie ułatwi testowanie jednostkowe.
sq33G
3
model! = zobacz model
Boris Yankov
2

Nie musisz owijać EDMX w nic.

Jeśli możesz przewidzieć możliwość zmiany z EF na inne podejście, możesz rozszerzyć swoje obiekty biznesowe (wykorzystując klasy częściowe) w celu implementacji interfejsów zdefiniowanych w osobnej warstwie obiektów biznesowych.

Następnie na podstawie kodu będziesz zajmować się tylko tymi interfejsami, a nie konkretnymi klasami generowanymi. Może być potrzebny trochę kodu kleju, aby trzymać to razem; że z EDMX może być twoim DAL.

sq33G
źródło
Więc jeśli nie będę tłumił żadnych zmian z EF na inne podejście, mój powyższy kod byłby w porządku? Miałbym wtedy tylko interfejs użytkownika i BLL (gdzie EDMX jest w BLL)?
Thomas
Moja pragmatyczna odpowiedź brzmi „tak”. Z zastrzeżeniem, że możesz chcieć umieścić EDMX w swoim własnym małym zestawie, jeśli będzie duży i w większości statyczny, abyś nie musiał go tak często rekompilować / redystrybuować.
sq33G
Ach, dobra uwaga na temat ponownej kompilacji / redystrybucji :)
Thomas
2

Istnieją dwa ogólne podejścia do nakładania warstw: ścisłe nakładanie warstw i zrelaksowane nakładanie warstw.

Ściśle warstwowe podejście ogranicza komponenty w jednej warstwie do interakcji tylko z równorzędnymi i z warstwą bezpośrednio poniżej.

Rozluźniona aplikacja warstwowa rozluźnia ograniczenia, dzięki czemu komponent może wchodzić w interakcje z komponentami z dowolnej dolnej warstwy.

Korzystanie z rozluźnionego nawarstwiania warstw może poprawić wydajność, ponieważ system nie musi przekierowywać prostych połączeń z jednej warstwy do drugiej. Z drugiej strony stosowanie swobodnego nakładania warstw nie zapewnia takiego samego poziomu izolacji między warstwami i utrudnia zamianę dolnej warstwy bez wpływu na wyższe warstwy.

W przypadku dużych rozwiązań obejmujących wiele komponentów oprogramowania często występuje duża liczba komponentów na tym samym poziomie abstrakcji, które nie są spójne. W takim przypadku każda warstwa może być dalej rozkładana na jeden lub więcej spójnych podsystemów. Rysunek 2 ilustruje możliwą notację UML (Unified Modeling Language) do reprezentowania warstw złożonych z wielu podsystemów.

wniosek: jeśli nie potrzebujesz środkowej warstwy, strac ją; nie wszystkie aplikacje wymagają tego samego podejścia i jakoś dodanie warstwy tylko do celów nakładania warstw będzie wiązało się z karami za złożoność kosztów i utrzymania.

omarqa
źródło