2012-09-25 1 views
2

나는 AutoMapper를 사용하기 시작하고 일부 의구심이 생기기 시작했습니다. dto를 도메인 모델로 매핑하는 올바른 방법은 어디입니까? 나는이 일을 해요 :DTO를 도메인 모델에 바인딩 할 위치

DTO :

public class PersonInsert 
{ 
    [Required] 
    public string Name { get; set; } 
    public string LastName { get; set; } 
} 

작업 :

[HttpPost] 
public ActionResult Insert(PersonInsert personInsert) 
{ 
    if (ModelState.IsValid) 
    { 
     new PersonService().Insert(personInsert); 

     return RedirectToAction("Insert"); 
    } 

    return View("Insert"); 
} 

서비스 :

public class PersonService 
{ 
    public int Insert(PersonInsert personInsert) 
    { 
     var person = Mapper.Map<PersonInsert, Person>(personInsert); 

     return new PersonRepository().Insert(person); 
    } 
} 

저장소 :

public class PersonRepository 
    { 
     internal int Insert(Person person) 
     { 
      _db.Person.Add(person); 
      _db.SaveChanges(); 

      return person.Id; 
     } 
    } 
,536,

그럼이게 맞습니까? 내 서비스가 도메인에 대해 알고 있어야합니까? 또는 저장소에 바인드 만 만들어야합니까? DTO에서 [Required]를 사용하는 것이 맞습니까?

답변

1

이 정보가 맞습니까? 나는 개인적으로 서비스를 갖는 아무 잘못 표시되지 않습니다

그것이 올바른 DTO에 [Required]를 사용하는

아니, DTO들은 어떠한 비즈니스 로직이 안되는 매핑을 . 이들은 순수하게 응용 프로그램의 다른 계층/계층에서 데이터를 전송하는 데 사용해야합니다.

DataAnnotations는 일반적으로 클라이언트/서버 측 유효성 검사를 위해 그러므로 내가 예를 들어, 당신의 Insert 행동에 대한 ViewModel를 모델로 다른 분리를 추가 도입 할 ViewModels에 사용된다

public class PersonViewModel  
{ 
    [Required] 
    public string Name { get; set; } 
    public string LastName { get; set; } 
} 

public class PersonDto 
{ 
    public string Name { get; set; } 
    public string LastName { get; set; } 
} 

작업 :

[HttpPost] 
public ActionResult Insert(PersonViewModel personViewModel) 
{ 
    if (ModelState.IsValid) 
    { 
     var personDto = Mapper.Map<PersonViewModel, PersonDto>(personViewModel); 
     new PersonService().Insert(personDto); 
     ... 
     } 
     ... 
    } 
} 

서비스 :

public class PersonService 
{ 
    public int Insert(PersonDto personDto) 
    { 
     var person = Mapper.Map<PersonDto, Person>(personDto); 

     return new PersonRepository().Insert(person); 
    } 
} 

그것은합니다 ([Required] 속성을 유일한 차이점이다 고려)이 시나리오에서 과잉 것처럼 보일 수 있습니다. 그러나 일반적인 MVC 응용 프로그램에서는 ViewModel과 비즈니스 모델을 명확하게 구분해야합니다.

+0

[필수]에 대해 어떻게해야합니까? asp.net-mvc는 ModelState.IsValid를 사용하여 사용자 입력의 유효성을 검사합니다.이 문제를 피하고 serviceLayer에서 논리 유효성 검사를 생성해야합니까? – MuriloKunze

+0

[필수] 주석을 어디에 넣으시겠습니까? Person 모델? –

+0

@murilokunze 내 대답을 참조하십시오. – James

1

ASP.NET MVC에서 DTO의 일반적인 사용은 viewmodel이라는 부분의 일부입니다. ViewModel은 하나 또는 여러 개의 DTO를 하나의 클래스로 결합하여 뷰 프리젠 테이션 및 서버에 값을 다시 게시하는 클래스입니다.

당신이하고있는 일은 정확하고 아무런 문제가 없지만 데이터 주석은 DTO가 아닌보기 모델에 있어야합니다. DTO를 뷰 모델이라고 부르지 않는 한, 그 모델은 괜찮습니다.

ASP에서 ViewModel과 모델 (도메인 모델)에 대한 다음 게시물을 읽으십시오.NET MVC 세계 :

희망이 내가 DTO에서 엔티티를 생성 거의 절대 것

4

을하는 데 도움이 - 나는 이유를 아래에 설명한다.

요청 :

public class InsertPersonRequest 
{ 
    [Required] 
    public string Name { get; set; } 
    public string LastName { get; set; } 
} 

작업 :

[HttpPost] 
public ActionResult Insert(InsertPersonViewModel viewModel) 
{ 
    if (ModelState.IsValid) 
    { 
     InsertPersonRequest request = InsertPersonViewModelMapper.CreateRequestFrom(viewModel); 
     new PersonService().Insert(request); 
     return RedirectToAction("Insert"); 
    } 

    return View("Insert"); 
} 

서비스 :

public class PersonService 
{ 
    public int Insert(InsertPersonRequest request) 
    { 
     var person = Person.Create(request.name, request.LastName);   
     return new PersonRepository().Insert(person); 
    } 
} 

저장소가 유지됩니다 난 공장 방법은 개체를 구축 할 수 있도록 요청 객체를 사용합니다 같은.

사람을 만들기위한 모든 로직이 사람의 팩토리 메소드 등 비즈니스 로직이 도메인의 캡슐화에있는이 방법 - 당신이 무엇인지와 파생 필드, 기본 필드 등

문제 UI에서 DTO를 생성 한 다음 모든 필드를 엔터티에 매핑해야합니다. 비즈니스 로직이 서비스 계층, UI 또는 예상치 못한 곳으로 스며들 수있는 확실한 방법입니다.

다시 읽어보십시오. 이것은 매우 심각한 실수입니다.

나는 그러나, DTO를 반환하는 서비스 계층에서 AutoMapper을 사용 :

서비스 :

public class PersonService 
{ 
    public PersonDto GetById(intid) 
    { 
     var person = new PersonRepository().GetById(id); 
     var personDto = Mapper.Map<Person, PersonDto>(person); 
     return personDto 
    } 
} 
+0

답을 많이 주셔서 감사하지만 질문이 있습니다. PersonDTO와 Person은 같은 속성을 가져야하지 않아야합니까? – MuriloKunze

+0

@murilokunze 달리 좋은 이유가 없다면 나는 그렇다고 말할 것입니다. –

1

나는 당신의 PersonService 도메인 층의 일부 (또는 응용 프로그램으로 볼 수 있다고 말할 것입니다 도메인 바로 위의 계층)와 컨트롤러 및 DTO는 그 위의 계층에 있습니다. 즉, PersonService 서명에서 DTO에 대한 참조를 가져 오지 말고 여기에서 도메인 Person 클래스를 사용하십시오. 따라서 매핑 코드는 컨트롤러에 있어야합니다. 이렇게하면 도메인 로직이 웹 서비스 계약의 변경에 영향을받지 않게되며 이는 실제로 PersonService을 사용하는 한 가지 방법 일 수 있습니다. 또한 은 구체적인 데이터 액세스 구현에 대해 더 이상 알 필요가 없기 때문에 PersonService에 주입 된 저장소 용 인터페이스를 소개합니다.

[Required] 속성의 경우 웹 서비스 메서드의 데이터 계약을 명시 했으므로 DTO에서이 문제가 발생하지 않습니다. 웹 서비스를 호출하는 사람은 누구나이 데이터 계약을 준수해야합니다. 물론이 요구 사항은 일반적으로 도메인 코드 어딘가에 예외를 던지면 반영됩니다.

+0

감사합니다. 예제를 단순화하기 위해 주입 코드를 작성하지 않았습니다. – MuriloKunze

1

[Required], MaxLength, Range 등과 같은 DTO에 주석을다는 것이 좋습니다.

DTO는 (신뢰할 수없는) 소스 (웹 사이트뿐만 아니라 다른 끝점, WCF 서비스 등)에서 들어올 수 있습니다.모든 요청은 서비스/비즈니스 계층에 전달되므로 비즈니스 논리를 수행하기 전에 입력 내용의 유효성을 검사해야합니다 (간단한 가드 검사). DTO에 주석을 달면 작업을 수행하는 데 필요한 입력을 간단히 설명합니다. 어노테이션이있는 객체를 전달하는 것은 유효성 검사가 아닙니다.

그러나 서비스/비즈니스 계층에서 DTO 정보가 올바른지 확인해야한다고 생각합니다. 주석은이를 확인하는 좋은 방법입니다.

상황에 대한 내 생각 :

관련 문제