Właśnie musiałem zmienić ORM i było to dość trudne zadanie, ponieważ logika zapytań przeciekała wszędzie. Gdybym kiedykolwiek musiał opracować nową aplikację, osobiście wolę enkapsulować całą logikę zapytań (używając ORM), aby zabezpieczyć ją przed zmianami. Wzorzec repozytorium jest dość kłopotliwy dla kodu i utrzymania, więc zastanawiałem się, czy istnieją jakieś inne wzorce rozwiązania problemu?
Mogę przewidzieć posty o nie dodawaniu dodatkowej złożoności, zanim będzie to naprawdę potrzebne, o zwinności itp., Ale interesują mnie tylko istniejące wzorce rozwiązujące podobny problem w prostszy sposób.
Moją pierwszą myślą było stworzenie repozytorium typu ogólnego, do którego w razie potrzeby dodaję metody do klas repozytorium typu za pomocą metod rozszerzenia, ale testowanie jednostkowe metod statycznych jest strasznie bolesne. TO ZNACZY:
public static class PersonExtensions
{
public static IEnumerable<Person> GetRetiredPeople(this IRepository<Person> personRep)
{
// logic
}
}
źródło
Odpowiedzi:
Przede wszystkim: ogólne repozytorium należy uznać za klasę podstawową, a nie za pełne implementacje. Powinno to pomóc w wprowadzeniu powszechnych metod CRUD. Ale nadal musisz zaimplementować metody zapytania:
Druga:
Nie wracaj
IQueryable
. To nieszczelna abstrakcja. Spróbuj zaimplementować ten interfejs samodzielnie lub korzystać z niego bez wiedzy o podstawowym dostawcy db. Na przykład każdy dostawca db ma własny interfejs API do chętnego ładowania jednostek. Dlatego jest to nieszczelna abstrakcja.Alternatywny
Alternatywnie możesz użyć zapytań (na przykład zdefiniowanych we wzorze rozdzielania poleceń / zapytań). CQS opisano w wikipedii.
Zasadniczo tworzysz klasy zapytań, które wywołujesz:
wielką zaletą zapytań jest to, że można używać różnych metod dostępu do danych dla różnych zapytań bez zaśmiecania kodu. możesz na przykład użyć usługi internetowej w jednej, nhibernate w drugiej, a ADO.NET w trzeciej.
Jeśli jesteś zainteresowany implementacją .NET, przeczytaj mój artykuł: http://blog.gauffin.org/2012/10/griffin-decoupled-the-queries/
źródło
YourProject.YourDomainModelName.Queries
łatwa w nawigacji.Najpierw myślę, że mówię, że ORM jest już wystarczająco duża abstrakcja w bazie danych. Niektóre ORM zapewniają powiązanie ze wszystkimi popularnymi relacyjnymi bazami danych (NHibernate ma powiązania z MSSQL, Oracle, MySQL, Postgress, itp.). Więc tworzenie nowej abstrakcji nie wydaje mi się opłacalne. Argumentowanie, że trzeba „wyabstrahować” tę ORM, jest bez znaczenia.
Jeśli nadal chcesz zbudować tę abstrakcję, byłbym przeciwny wzorowi repozytorium. Był świetny w erze czystego SQL, ale jest dość kłopotliwy w obliczu współczesnej ORM. Głównie dlatego, że ostatecznie wdrażasz większość funkcji ORM, takich jak operacje CRUD i zapytania.
Gdybym miał budować takie abstrakcje, użyłbym tych zasad / wzorów
W konkretnej implementacji użyłbym operacji CRUD ORM bezpośrednio, bez owijania. Zrobiłbym również proste zapytania bezpośrednio w kodzie. Ale złożone zapytania byłyby zamknięte w ich własnych obiektach. Aby „ukryć” ORM, próbowałbym transparentnie wstrzyknąć kontekst danych do obiektów usługi / interfejsu użytkownika i zrobić to samo z obiektami zapytań.
Ostatnią rzeczą, którą chciałbym powiedzieć, jest to, że wiele osób korzysta z ORM, nie wiedząc, jak go używać i jak najlepiej z niego „czerpać zyski”. Ludzie polecający repozytoria są zwykle tego rodzaju.
Jako lekturę polecam blog Ayende , szczególnie ten artykuł .
źródło
Problem z nieszczelną implementacją polega na tym, że potrzebujesz wielu różnych warunków filtrowania.
Możesz zawęzić ten interfejs, jeśli zaimplementujesz metodę repozytorium FindByExample i użyjesz jej w ten sposób
źródło
Zastanów się, czy twoje rozszerzenia działają na IQueryable zamiast IRepository.
Aby przeprowadzić test jednostkowy:
Do testowania nie jest wymagane wyśmiewanie kibiców. Możesz także łączyć te metody rozszerzeń, aby w razie potrzeby tworzyć bardziej złożone zapytania.
źródło
IQueryable
jest złą matką, a raczej interfejsem BOGA. Wdrażanie go jest bardzo potrzebne i jest bardzo mało (jeśli w ogóle) kompletnych LINQ do dostawców Sql. b) Metody przedłużania uniemożliwiają przedłużenie (jedna z podstawowych zasad OOP).Napisałem całkiem fajny wzorzec obiektu zapytania dla NHibernate tutaj: https://github.com/shaynevanasperen/NHibernate.Sessions.Operations
Działa przy użyciu takiego interfejsu:
Biorąc pod uwagę klasę jednostki POCO taką jak ta:
Możesz budować obiekty zapytania takie jak to:
A następnie użyj ich w następujący sposób:
źródło