Jak wdrożyć wzorzec repozytorium dla złożonych modeli obiektów?

21

Nasz model danych ma prawie 200 klas, które można podzielić na kilkanaście obszarów funkcjonalnych. Byłoby miło używać domen, ale separacja nie jest tak czysta i nie możemy jej zmienić.

Przeprojektowujemy nasz DAL, aby korzystać z Entity Framework, a większość rekomendacji, które widziałem, sugeruje użycie wzorca repozytorium. Jednak żadna z próbek tak naprawdę nie dotyczy złożonych modeli obiektowych. Niektóre implementacje, które znalazłem, sugerują użycie repozytorium na jednostkę. Wydaje się to niedorzeczne i niemożliwe do utrzymania w przypadku dużych, złożonych modeli.

Czy naprawdę konieczne jest utworzenie UnitOfWork dla każdej operacji i repozytorium dla każdej jednostki? Mogę skończyć z tysiącami zajęć. Wiem, że jest to nieuzasadnione, ale znalazłem bardzo niewiele wskazówek dotyczących wdrażania Repozytorium, Jednostki Pracy i Entity Framework w odniesieniu do złożonych modeli i realistycznych aplikacji biznesowych.

Eric Falsken
źródło

Odpowiedzi:

6

Najpierw przejrzysz każdy posiadany byt i zadasz sobie pytanie:

Czy ma sens utrzymywanie tego bytu w spokoju?

Chodzi mi tutaj o to, że w twoim modelu obiektowym niektóre byty są prawdopodobnie zawarte w innych w relacji master-detail. Jeśli twoja jednostka jest wysoce zależna od innej, nie twórz repozytorium dla samej encji, ponieważ prawdopodobnie nie będzie ona utrwalona sama. Zamiast tego utworzysz repozytorium dla każdej klasy nadrzędnej i upewnisz się, że elementy potomne i inne relacje zostaną zachowane w tym samym czasie.

Nie podoba mi się, jak zaimplementowali wzorzec UnitOfWork w podanym linku. Sugeruję, aby zrobić coś więcej zgodnie z tymi zasadami . Nie musisz definiować jednej klasy dla repozytorium. Ta sama klasa może być używana dla każdego repozytorium, z których każde ma własną instancję klasy UnitOfWork na czas trwania operacji. Możesz także ponownie użyć tego samego UnitOfWork w różnych repozytoriach do zmian, które chcesz zachować w tym samym czasie.

marco-fiset
źródło
Niezły link! Sprawdzam to.
Eric Falsken
Twój link (i odpowiedź) był najbardziej pomocny, chociaż ostatecznie nie wykorzystałem podanych wzorów. Skończyło się na tym, że użyłem klasy otoki, która pośredniczyła w metodach Add / Attach / Remove / SaveChanges, aby działać jako ogólne repozytorium, a następnie dodałem metodę Query / QuerySingle / QueryAll, która akceptuje niestandardowe klasy zapytań do przechowywania mojej implementacji zapytania. Działa to ładnie, dzięki czemu mogę wykonywać zapytania LINQ i T-SQL bez bezpośredniego zaangażowania EF.
Eric Falsken,
Entity Framework, z wykorzystaniem transakcji, jest już implementacją wzorca Unit of Work.
Greg Burghardt
1
link nie działa ...
Newtopian,
3

Może powinieneś rzucić okiem na projektowanie oparte na domenie . Zaleca się grupowanie obiektów w Agregaty i tworzenie repozytoriów tylko dla encji Root każdej Agregacji. To dobry sposób na uporządkowanie dużego złożonego modelu obiektowego.

Twoje różne obszary funkcjonalne mogą być ograniczonymi kontekstami . Istnieją różne techniki radzenia sobie z nakładającymi się ograniczonymi kontekstami, jeśli ich rozdzielenie nie jest jasne.

guillaume31
źródło
0

Jakie podstawy teoretyczne znalazłeś dla projektu bazy danych „Wzorzec repozytorium”? Nie sądzę. Jest to warstwa złożoności oparta na fałszywym założeniu: że „warstwa trwałości” jest czymś, od czego trzeba się odizolować. Z tego, co mogę powiedzieć, chodzi o powszechną niewiedzę programistyczną o relacyjnych zasadach projektowania, a także o założoną centralną rolę projektowania aplikacji. Nie uzasadnia to jednak istnienia na racjonalnych, nie mówiąc już teoretycznych podstawach.

Jedna prawdziwa ścieżka do projektu bazy danych nie zmieniła się od 30 lat: analizuj dane. Znajdź klucze i ograniczenia oraz relacje „jeden do jednego”. Zaprojektuj swoje stoły zgodnie z normalną formą Boyce-Codd. Użyj widoków i procedur przechowywanych, aby ułatwić dostęp do danych.

Być może niekochany SQL DBMS zapewnia lepszą warstwę izolacyjną niż wszystko, co może zapewnić programista. Prawdą jest, że wraz ze zmianą bazy danych SQL używany do uzyskania dostępu może ulec zmianie. Pamiętaj jednak, że jest to prawdą niezależnie od tego, czy istnieje warstwa mediacyjna . Tak długo, jak aplikacja korzysta z widoków i procedur przechowywanych w celu uzyskania dostępu do DBMS, zwykłe narzędzia inżynierskie SQL będą wskazywać, kiedy zmiany w bazowej bazie danych unieważnią te widoki i procedury przechowywane.

Na tym polega oczywiście wyzwanie. Warstwa mediacyjna zapewnia złudzenie izolacji i wygodę dla programisty pisania kodu, który wie, jak to zrobić. Nauka projektowania baz danych i SQL wymaga nauczenia się czegoś nowego. Większość ludzi woli umrzeć niż myśleć, a wielu odnosi sukcesy.

Ktoś z twojego zespołu bez wątpienia sprzeciwi się temu, że pisanie SQL w celu obsługi 200 klas to dużo pracy. Bez wątpienia. Ale to przynajmniej przydatna praca. Jeśli projektujesz bazę danych naśladując projekt OO, wykonasz również dużo pracy, w większości bezużytecznej i pokonasz większość tego, co oferuje DBMS.

Na przykład, rozważasz odzwierciedlenie jednostki pracy w bazie danych (zakładam, że jako tabelę lub tabele). Jednostka pracy jest wbudowany w służbie DBMS: begin transaction... ... aktualizacji bazy danych commit transaction. Nic do modelowania, oprócz mapowania klas na tabele bazy danych w SQL.

Twoje pytanie zostało opublikowane 4 lata temu. Odpowiadam, ponieważ ostatnio został w jakiś sposób „zaktualizowany”, co oznacza, że ​​nadal jest dla kogoś interesujący. Mam nadzieję, że moja odpowiedź zachęca czytelnika do zastosowania podstawowej teorii relacyjnej do problemu zamiast przyjmowania bezsensownego obejścia.

James K. Lowden
źródło