[asp.net-mvc] 리포지토리와 서비스 계층의 차이점은 무엇입니까?

OOP 디자인 패턴에서 리포지토리 패턴과 서비스 계층의 차이점은 무엇입니까?

ASP.NET MVC 3 앱을 개발 중이며 이러한 디자인 패턴을 이해하려고 노력하고 있지만 제 뇌는 그것을 얻지 못하고 있습니다.



답변

리포지토리 레이어는 데이터 액세스에 대한 추가적인 추상화 수준을 제공합니다. 쓰는 대신

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

데이터베이스에서 단일 항목을 가져 오려면 저장소 인터페이스를 사용하십시오.

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

전화하십시오 Get(id). 리포지토리 레이어는 기본 CRUD를 노출합니다 작업을 합니다.

서비스 계층은 리포지토리를 사용하는 비즈니스 로직을 노출합니다. 서비스 예는 다음과 같습니다.

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);
}

List()저장소의 메소드는 모든 사용자를 리턴 하지만 ListUsers()IUserService의 사용자는 하나만 리턴 할 수 있으며 사용자는 액세스 할 수 있습니다.

ASP.NET MVC + EF + SQL SERVER에는 다음과 같은 통신 흐름이 있습니다.

보기 <-컨트롤러-> 서비스 계층-> 리포지토리 계층-> EF-> SQL Server

서비스 계층-> 리포지토리 계층-> EF 이 부분은 모델에서 작동합니다.

뷰 <-컨트롤러-> 서비스 계층 이 부분은 뷰 모델에서 작동합니다.

편집하다:

/ Orders / ByClient / 5의 흐름 예 (특정 클라이언트의 순서를보고 싶습니다) :

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);
    }
}

주문 서비스를위한 인터페이스입니다.

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

이 인터페이스는 뷰 모델을 반환합니다.

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

인터페이스 구현입니다. 모델 클래스와 저장소를 사용하여 뷰 모델을 작성합니다.

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...}
             }
         );
     }
}


답변

Carnotaurus는 저장소가 데이터를 스토리지 형식에서 비즈니스 오브젝트로 맵핑 할 책임이 있다고 말했다. 스토리지에서 데이터를 읽고 쓰는 방법 (삭제, 업데이트도 모두)을 처리해야합니다.

반면에 서비스 계층의 목적은 비즈니스 재사용을 단일 장소로 캡슐화하여 코드 재사용 및 문제 분리를 촉진하는 것입니다. Asp.net MVC 사이트를 구축 할 때 이것이 실제로 실제로 의미하는 것은이 구조를 가지고 있다는 것입니다

[제어기]는 [서비스]를 호출합니다.

내가 찾은 유용한 한 가지 원칙은 컨트롤러 및 리포지토리에서 로직을 최소로 유지하는 것입니다.

컨트롤러에서는 DRY를 유지하는 데 도움이되기 때문입니다. 다른 곳에서 동일한 필터링 또는 논리를 사용해야하는 것이 매우 일반적이며 컨트롤러에 배치하면 재사용 할 수 없습니다.

리포지토리에서 더 나은 것이 나올 때 스토리지 (또는 ORM)를 교체 할 수 있기를 원하기 때문입니다. 그리고 저장소에 논리가 있으면 저장소를 변경할 때이 논리를 다시 작성해야합니다. 내 저장소가 IQueryable 만 반환하고 서비스가 필터링을 수행하는 경우 매핑 만 교체하면됩니다.

예를 들어 최근 몇 개의 Linq-To-Sql 리포지토리를 EF4로 교체했으며이 원칙을 지키지 않은 분은 몇 분 안에 교체 할 수있었습니다. 내가 몇 가지 논리를 가지고있는 곳은 대신 몇 시간의 문제였습니다.


답변

받아 들여진 대답 (그리고 수백 번의 찬성)에는 큰 결함이 있습니다. 나는 이것을 주석에서 지적하고 싶었지만 30 개의 주석으로 거기에 묻힐 것입니다.

그런 식으로 구축 된 엔터프라이즈 응용 프로그램을 인수했으며 초기 반응은 WTH 입니까? 서비스 계층의 ViewModel? 수년간의 개발로 인해 협약을 변경하고 싶지 않았으므로 ViewModels를 계속 반환했습니다. 우리가 WPF를 사용하기 시작했을 때 그것은 악몽으로 변했습니다. 우리 (개발팀)는 항상 말하고 있습니다 : 어떤 ViewModel? 실제 하나 (WPF를 위해 작성한 것) 또는 서비스 하나? 웹 응용 프로그램 용으로 작성되었으며 심지어 UI에서 편집을 비활성화하기 위해 IsReadOnly 플래그가 있었습니다 . 한 단어로 인한 주요 결함 및 주요 결함 : ViewModel !!

같은 실수를 저지르기 전에, 위의 이야기 외에도 몇 가지 이유가 있습니다.

서비스 계층에서 ViewModel을 반환하는 것은 엄청난 일이 아닙니다. 그것은 다음과 같습니다.

  1. 이러한 서비스를 사용하려면 MVVM을 사용하는 것이 좋으며 여기에 사용해야하는 ViewModel이 있습니다. 아야!

  2. 서비스는 UI 어딘가에 표시 될 것이라고 가정합니다. 웹 서비스 나 Windows 서비스와 같은 비 UI 응용 프로그램에서 사용하는 경우 어떻게됩니까?

  3. 그것은 심지어 실제 ViewModel이 아닙니다. 실제 ViewModel에는 관찰 성, 명령 등이 있습니다. 이름이 잘못된 POCO 일뿐입니다. (이름이 중요한 이유는 위의 내 이야기를 참조하십시오.)

  4. 소비 애플리케이션은 프리젠 테이션 레이어 (ViewModel이이 레이어에서 사용됨)이고 C #을 더 잘 이해합니다. 또 다른 아야!

제발 하지마!


답변

일반적으로 리포지토리는 엔티티를 채우는 스캐 폴딩으로 사용됩니다. 서비스 계층은 나가서 요청을 소싱합니다. 서비스 계층 아래에 ​​리포지토리를 배치 할 수 있습니다.


답변

리포지토리 계층은 데이터베이스에 액세스하기 위해 구현되며 데이터베이스에서 CRUD 작업을 확장하는 데 도움이됩니다. 서비스 계층은 응용 프로그램의 비즈니스 논리로 구성되며 저장소 계층을 사용하여 데이터베이스와 관련된 특정 논리를 구현할 수 있습니다. 응용 프로그램에서는 별도의 리포지토리 계층과 서비스 계층을 갖는 것이 좋습니다. 별도의 리포지토리와 서비스 계층이 있으면 코드가 더 모듈화되고 데이터베이스가 비즈니스 로직에서 분리됩니다.


답변