Różnica między warstwą repozytorium a usługą?

W wzorcach projektowych OOP, jaka jest różnica między wzorcem repozytorium a warstwą usług?

Pracuję nad ASP.NET aplikacja MVC 3 i staram się zrozumieć te wzorce projektowe, ale mój mózg po prostu tego nie rozumie...jeszcze!!

Author: Sam, 2011-02-19

5 answers

Warstwa repozytorium daje dodatkowy poziom abstrakcji nad dostępem do danych. Zamiast pisać

var context = new DatabaseContext();
return CreateObjectQuery<Type>().Where(t => t.ID == param).First();

Aby pobrać pojedynczy element z bazy danych, należy użyć interfejsu repozytorium

public interface IRepository<T>
{
    IQueryable<T> List();
    bool Create(T item);
    bool Delete(int id);
    T Get(int id);
    bool SaveChanges();
}

I zadzwoń Get(id). Warstwa repozytorium wyświetla podstawowe operacje CRUD .

Warstwa usług wyświetla logikę biznesową, która korzysta z repozytorium. Przykładowa usługa może wyglądać następująco:

public interface IUserService
{
    User GetByUserName(string userName);
    string GetUserNameByEmail(string email);
    bool EditBasicUserData(User user);
    User GetUserByID(int id);
    bool DeleteUser(int id);
    IQueryable<User> ListUsers();
    bool ChangePassword(string userName, string newPassword);
    bool SendPasswordReminder(string userName);
    bool RegisterNewUser(RegisterNewUserModel model);
}

Podczas gdy List() metoda repozytorium zwraca wszystkich użytkowników, ListUsers() IUserService może zwrócić tylko te, do których Użytkownik ma dostęp.

W ASP.NET MVC + EF + SQL SERVER, mam taki przepływ komunikacji:

Views Service layer -> repozytorium layer -> EF - > SQL Server

Warstwa usług - > warstwa repozytoriów - > EF ta część działa na modelach.

Views Service layer ta część działa na modelach widoków.

EDIT:

Przykład przepływu dla W związku z tym, że nie jest to możliwe, nie jest to konieczne.]}

public class OrderController
{
    private IOrderService _orderService;

    public OrderController(IOrderService orderService)
    {
        _orderService = orderService; // injected by IOC container
    }

    public ActionResult ByClient(int id)
    {
        var model = _orderService.GetByClient(id);
        return View(model); 
    }
}

To jest interfejs do obsługi zamówień:

public interface IOrderService
{
    OrdersByClientViewModel GetByClient(int id);
}

Ten interfejs zwraca model widoku:

public class OrdersByClientViewModel
{
     CientViewModel Client { get; set; } //instead of ClientView, in simple project EF Client class could be used
     IEnumerable<OrderViewModel> Orders { get; set; }
}

To implementacja interfejsu. Używa klas modelu i repozytorium do tworzenia modelu widoku:

public class OrderService : IOrderService
{
     IRepository<Client> _clientRepository;
     public OrderService(IRepository<Client> clientRepository)
     {
         _clientRepository = clientRepository; //injected
     }

     public OrdersByClientViewModel GetByClient(int id)
     {
         return _clientRepository.Get(id).Select(c => 
             new OrdersByClientViewModel 
             {
                 Cient = new ClientViewModel { ...init with values from c...}
                 Orders = c.Orders.Select(o => new OrderViewModel { ...init with values from o...}     
             }
         );
     }
}
 277
Author: LukLed,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-22 22:50:48

Jak powiedział Carnotaurus repozytorium jest odpowiedzialne za mapowanie danych z formatu przechowywania do obiektów biznesowych. Powinien obsługiwać zarówno odczyt, jak i zapis danych (usuwanie, aktualizacja też) z I do magazynu.

[[0]} celem warstwy usług z drugiej strony jest hermetyzacja logiki biznesowej w jednym miejscu w celu promowania ponownego użycia kodu i rozdzielenia obaw. Co to zwykle oznacza dla mnie w praktyce przy budowaniu Asp.net MVC witryn jest to, że mam to struktura

[Kontroler] wywołuje [usługi] kto wywołuje [repozytorium]

Jedną z zasad, które uznałem za użyteczne, jest ograniczenie logiki do minimum w kontrolerach i repozytoriach.

W kontrolerach to dlatego, że pomaga utrzymać mnie w suchości. Bardzo często muszę używać tego samego filtrowania lub logiki gdzie indziej i jeśli umieściłem go w kontrolerze, nie mogę go ponownie użyć.

W repozytoriach to dlatego, że chcę mieć możliwość wymiany pamięci (lub ORM), gdy coś lepiej będzie. A jeśli mam logikę w repozytorium, muszę przepisać tę logikę, gdy zmieniam repozytorium. Jeśli moje repozytorium zwróci tylko IQueryable, a usługa zrobi filtrowanie z drugiej strony, będę musiał tylko wymienić mapowania.

Na przykład niedawno wymieniłem kilka moich repozytoriów Linq-to-Sql na EF4, a te, w których byłem wierny tej zasadzie, mogły zostać zastąpione w ciągu kilku minut. Gdzie miałem trochę logiki, to była kwestia godzin.

 32
Author: Mikael Eliasson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-19 17:42:15

Zazwyczaj repozytorium jest używane jako rusztowanie do wypełniania Twoich podmiotów - warstwa usług wyjdzie i wywoła żądanie. Jest prawdopodobne, że umieścisz repozytorium pod warstwą usług.

 7
Author: CarneyCode,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-02-19 06:59:47

Zaakceptowana odpowiedź (i upvoted setki razy) ma poważną wadę. Chciałem to zwrócić uwagę w komentarzu, ale to będzie po prostu Zakopane tam w 30 coś komentarze, więc wskazując tutaj.

Przejąłem zbudowaną w ten sposób aplikację korporacyjną i moją początkową reakcją było WTH ? ViewModels w warstwie usług? Nie chciałem zmieniać konwencji, ponieważ lata rozwoju poszły w to, więc kontynuowałem powracanie ViewModels. Boy it turned into koszmar, kiedy zaczęliśmy używać WPF. My (zespół deweloperów) zawsze mówiliśmy: który ViewModel? Prawdziwy (ten, który napisaliśmy dla WPF) czy serwisowy? Zostały one napisane dla aplikacji webowej i miały nawet flagę IsReadOnly , aby wyłączyć edycję w interfejsie użytkownika. Główna, główna wada i wszystko przez jedno słowo: ViewModel !!

Zanim popełnisz ten sam błąd, oto kilka innych powodów oprócz mojej historii powyżej:

Zwracanie modelu widoku z warstwy usługi to wielkie Nie Nie. To jak powiedzenie:

  1. Jeśli chcesz korzystać z tych usług, lepiej używaj MVVM i oto model widoku, którego potrzebujesz. Ouch!

  2. Usługi zakładają, że będą wyświetlane gdzieś w interfejsie użytkownika. Co jeśli jest używany przez aplikacje spoza interfejsu użytkownika, takie jak usługi sieciowe lub usługi windows?

  3. To nawet nie jest prawdziwy ViewModel. prawdziwy ViewModel ma obserwowalność, komendy itp. To jest poco ze złą sławą. (Zobacz moją historię powyżej, dlaczego nazwy mają znaczenie.)

  4. Aplikacja powinna być warstwą prezentacji (ViewModels są używane przez tę warstwę) i lepiej zrozumieć C#. / Align = "Left" /

Proszę, nie rób tego!

 5
Author: CodingYoshi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-15 04:13:26

Warstwa repozytorium jest zaimplementowana w celu uzyskania dostępu do bazy danych i pomaga rozszerzyć operacje CRUD na bazie danych. Natomiast warstwa usługowa składa się z logiki biznesowej aplikacji i może wykorzystywać warstwę repozytorium do implementacji pewnej logiki związanej z bazą danych. W aplikacji lepiej jest mieć oddzielną warstwę repozytorium i warstwę usługi. Osobne warstwy repozytorium i usługi sprawiają, że kod jest bardziej modułowy i oddziela bazę danych od logiki biznesowej.

 1
Author: Akshay,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-30 15:46:17