Wzorzec repozytorium jest abstrakcją . Ma to na celu zmniejszenie złożoności i uczynienie reszty kodu trwałą ignorancją. Jako bonus umożliwia pisanie testów jednostkowych zamiast testów integracyjnych .
Problem polega na tym, że wielu programistów nie rozumie celu wzorców i nie tworzy repozytoriów, które przeciekają określone informacje do dzwoniącego (zwykle przez ujawnienie IQueryable<T>
). W ten sposób nie odnoszą korzyści z bezpośredniego korzystania z sali operacyjnej / M.
Zaktualizuj, aby zająć się inną odpowiedzią
Kodowanie wyjątku
Korzystanie z repozytoriów nie polega na możliwości przełączania technologii trwałości (tj. Zmiany bazy danych lub korzystania z usługi sieciowej itp.). Chodzi o oddzielenie logiki biznesowej od trwałości, aby zmniejszyć złożoność i powiązania.
Testy jednostkowe a testy integracyjne
Nie piszesz testów jednostkowych dla repozytoriów. Kropka.
Ale wprowadzając repozytoria (lub jakąkolwiek inną warstwę abstrakcji między trwałością a biznesem), możesz pisać testy jednostkowe dla logiki biznesowej. tzn. nie musisz się martwić, że testy zakończą się niepowodzeniem z powodu nieprawidłowo skonfigurowanej bazy danych.
Co do pytań. Jeśli używasz LINQ, musisz również upewnić się, że zapytania działają, tak samo jak w przypadku repozytoriów. i odbywa się to za pomocą testów integracyjnych.
Różnica polega na tym, że jeśli nie pomieszałeś swojej firmy z instrukcjami LINQ, możesz mieć 100% pewności, że to Twój kod trwałości zawodzi, a nie coś innego.
Jeśli przeanalizujesz swoje testy, zobaczysz również, że są one znacznie czystsze, jeśli nie masz mieszanych obaw (np. Logika LINQ + Business)
Przykłady repozytoriów
Większość przykładów to bzdury. to jest bardzo prawdziwe. Jeśli jednak wygooglujesz jakiś wzór projektu, znajdziesz wiele kiepskich przykładów. Nie ma powodu, aby unikać używania wzoru.
Zbudowanie poprawnej implementacji repozytorium jest bardzo łatwe. W rzeczywistości musisz przestrzegać tylko jednej zasady:
Nie dodawaj niczego do klasy repozytorium aż do momentu, gdy tego potrzebujesz
Wielu programistów jest leniwych i próbuje utworzyć ogólne repozytorium i użyć klasy bazowej z wieloma metodami, których mogą potrzebować. YAGNI. Piszesz klasę repozytorium raz i przechowujesz ją tak długo, jak działa aplikacja (może to być lata). Po co to spieprzyć będąc leniwym. Utrzymuj go w czystości bez dziedziczenia klasy bazowej. Ułatwi to czytanie i konserwację.
(Powyższe stwierdzenie jest wskazówką, a nie prawem. Klasę bazową można bardzo dobrze zmotywować. Pomyśl tylko, zanim ją dodasz, aby dodać ją z właściwych powodów)
Starocie
Wniosek:
Jeśli nie masz nic przeciwko umieszczaniu instrukcji LINQ w kodzie biznesowym ani nie przejmujesz się testami jednostkowymi, nie widzę powodu, aby nie używać Entity Framework bezpośrednio.
Aktualizacja
Napisałem na blogu zarówno o wzorcu repozytorium, jak io tym, co naprawdę oznacza „abstrakcja”: http://blog.gauffin.org/2013/01/repository-pattern-done-right/
Zaktualizuj 2
W przypadku pojedynczego typu encji z ponad 20 polami, w jaki sposób zaprojektujesz metodę zapytania, aby obsługiwała dowolną kombinację permutacji? Nie chcesz ograniczać wyszukiwania tylko po nazwie, a co z wyszukiwaniem za pomocą właściwości nawigacji, wystawiaj wszystkie zamówienia z pozycją z określonym kodem ceny, 3 poziomy wyszukiwania właściwości nawigacji. Cały powód IQueryable
został wymyślony, aby móc skomponować dowolną kombinację wyszukiwania w bazie danych. W teorii wszystko wygląda świetnie, ale potrzeba użytkownika wygrywa nad teorią.
Ponownie: jednostka z ponad 20 polami jest nieprawidłowo modelowana. To istota BOGA. Rozbicie go.
Nie twierdzę, że IQueryable
to nie było do zadawania pytań. Mówię, że nie jest to właściwe dla warstwy abstrakcji, takiej jak wzór repozytorium, ponieważ jest nieszczelna. Nie ma dostawcy LINQ To Sql w 100% kompletnego (takiego jak EF).
Wszystkie mają specyficzne dla implementacji rzeczy, takie jak używanie przyspieszonego / leniwego ładowania lub wykonywanie instrukcji SQL „IN”. Wystawienie IQueryable
w repozytorium zmusza użytkownika do poznania tych wszystkich rzeczy. Zatem cała próba wyodrębnienia źródła danych kończy się całkowitą porażką. Po prostu dodajesz złożoność bez żadnych korzyści z bezpośredniego korzystania z OR / M.
Albo poprawnie zaimplementuj wzorzec repozytorium, albo po prostu go nie używaj.
(Jeśli naprawdę chcesz obsługiwać duże jednostki, możesz połączyć wzorzec Repozytorium ze wzorcem Specification . To daje pełną abstrakcję, którą można również przetestować).