2013-11-01 3 views
5

내 프로젝트의 서비스 레이어가있는 저장소 패턴을 따르고 있습니다. 각 뷰에 대해 viewmodel을 생성 할 것입니다.ASP.NET MVC 서비스 레이어 입력 출력 데이터

서비스 레이어가 도메인 개체에 직접 액세스하여 컨트롤러에 반환해야하는지, 아니면 DTO를 사용해야하는지 혼란 스럽습니다. DTO를 사용해야한다면 프로젝트 아키텍처에 DTO를 둘 수 있습니까?

감사합니다.

답변

9

서비스 레이어는 적절한 business logic을 구현하여 Dto 개체와 도메인 개체를 매핑 (변환)합니다.

DTO 개체는 컨트롤러와 서비스에서 사용해야합니다.

DTO 년대 반면 도메인 오브젝트에, 컨트롤러 및 서비스 사이에 옮겨진되는 도메인에 대해 알고하지 않는 서비스 및 저장소

컨트롤러 사이에 옮겨진하고 저장소는 DTO에 대해 알고하지 않습니다. 서비스는 DTO와 도메인을 모두 알고 있고, 당신과 나 사이의 stackoverflow와 같은 드라이버와 도로 사이의 차 같은 비즈니스 규칙을 가지고 서로를 서로 변환합니다.

다음 코드는 예제입니다. 각 네임 스페이스가 하나의 패키지라고 생각하십시오.

namespace Controllers 
{ 
    using Services; 
    using DataTransferObjects; 

    public class CoffeeController 
    { 
     public ICoffeeService CoffeeService { get; set; } 

     public JsonResult GetCoffee(GetCoffeeInDto inDto) 
     { 
      var result = CoffeeService.GetCoffee(inDto); 
      return JsonResult(result); 
     } 

     public JsonResult SaveCoffee(SaveCoffeeInDto inDto) 
     { 
      var outDto = CoffeeService.SaveCoffee(inDto); 
      return JsonResult(outDto); 
     } 
    } 
} 

namespace Services 
{ 
    using DataTransferObjects; 
    public interface ICoffeeService 
    { 
     GetCoffeeOutDto GetCoffee(GetCoffeeInDto inDto); 
     SaveCoffeeOutDto SaveCoffee(SaveCoffeeInDto inDto); 
    } 
} 

namespace Services.Impl 
{ 
    using Services; 
    using Repository; 
    using DataTransferObjects; 
    using Domain; 

    public class CoffeeService : ICoffeeService 
    { 
     public ICoffeeRepository CoffeeRepository { get; set; } 
     public GetCoffeeOutDto GetCoffee(GetCoffeeInDto inDto) 
     { 
      var entity = CoffeeRepository.Get(inDto.Id); 
      return new GetCoffeeOutDto {Id = entity.Id, Name = entity.Name}; 
     } 

     public SaveCoffeeOutDto SaveCoffee(SaveCoffeeInDto inDto) 
     { 
      var entity = new CoffeeEntity {Name = inDto.Name}; 
      CoffeeRepository.Save(entity); 
      return new SaveCoffeeOutDto {Id = entity.Id}; 
     } 
    } 
} 

namespace Repository 
{ 
    using Domain; 
    public interface ICoffeeRepository 
    { 
     CoffeeEntity Get(int id); 
     void Save(CoffeeEntity coffeeEntity); 
    } 
} 

namespace Repository.Impl 
{ 
    using Repository; 
    using Domain; 

    public class CoffeeRepository:ICoffeeRepository 
    { 
     public CoffeeEntity Get(int id) 
     { 
      //get entity from db 
      throw new System.NotImplementedException(); 
     } 

     public void Save(CoffeeEntity coffeeEntity) 
     { 
      //insert entity into db 
      throw new System.NotImplementedException(); 
     } 
    } 
} 

namespace DataTransferObjects 
{ 
    public class SaveCoffeeInDto 
    { 
     public string Name { get; set; } 
    } 

    public class SaveCoffeeOutDto 
    { 
     public int Id { get; set; } 
    } 

    public class GetCoffeeInDto 
    { 
     public int Id { get; set; } 
    } 

    public class GetCoffeeOutDto 
    { 
     public int Id { get; set; } 
     public string Name { get; set; } 
    } 
} 

namespace Domain 
{ 
    public class CoffeeEntity 
    { 
     public int Id { get; set; } 
     public string Name { get; set; } 
    } 
} 
+0

CoffeeEntity를 GetCoffeeInDto가 아닌 컨트롤러로 보내면 아키텍처 규칙을 위반합니까? DTO를 사용하기 위해 도메인 객체를 다시 작성하는 것처럼 보입니다. – SherleyDev

+0

예, 컨트롤러에 엔티티를 보내면 아키텍처를 위반하게됩니다. 그러나 프로젝트가 크지 않고 비즈니스가 충분히 복잡하지 않으면이 아키텍처를 사용할 필요가 없습니다. Dto 및 Entity와 같은 객체 분리는 정보와 데이터를 구별하는 것입니다. 관심 원칙의 분리와 관련하여 데이터 계층에서 데이터를 가지고 놀고 표현 계층에서 정보를 가지고 노는 것은 별도의 관심사로 간주되어 별도의 클래스 구현을 사용하여 유지됩니다. – mecek

+0

+1 훌륭한 답변입니다. @ SherleyDev 여기 좀보세요 : http://stackoverflow.com/a/21569720/654708 자세한 답변입니다. 컨트롤러를 도메인 모델에 바인딩하는 것이 본질적으로 나쁘지는 않습니다. 소규모 프로젝트의 경우 DTO 생성은 과도한 것으로 간주 될 수 있습니다. – GFoley83