2

AutoMapperを使い始めましたが、いくつか疑問が生じました。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;
        }
     }

それで、これは正しいですか?私のサービスはドメインについて知っている必要がありますか?または、リポジトリでのみバインドする必要がありますか?DTOで[必須]を使用するのは正しいですか?

4

5 に答える 5

4

DTOからエンティティを作成することはほとんどありません-理由を以下に説明します。リクエストオブジェクトを使用して、ファクトリメソッドでエンティティを構築できるようにします。

リクエスト:

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

リポジトリは同じままです。

このように、Personを作成するためのすべてのロジックは、PersonのFactoryメソッドに配置されるため、ビジネスロジックはドメインにカプセル化されます(派生フィールド、デフォルトフィールドなど)。

あなたがしていることの問題は、DTOをUIで作成する必要があることです。その後、すべてのフィールドがエンティティにマップされます。これは、ビジネスロジックがサービスレイヤー、UI、またはそれが存在する場所に浸透するための確実な方法です。あるべきではありません。

もう一度お読みください-これは非常に深刻な間違いであり、何度も何度も繰り返されています。

ただし、サービスレイヤーでAutoMapperを使用して、DTOを返します。

サービス:

public class PersonService 
{ 
    public PersonDto GetById(intid) 
    { 
        var person = new PersonRepository().GetById(id);
        var personDto = Mapper.Map<Person, PersonDto>(person); 
        return personDto
    } 
} 
于 2012-09-25T14:42:41.347 に答える
2

これは正しいです?

私は個人的にあなたのサービスにマッピングを行わせることに何の問題も見ていません

[Required]DTOで使用するのは正しいですか

いいえ、DTOにはビジネスロジックがまったくないはずです。これらは、アプリケーションのさまざまな層/層を介してデータを送信するためだけに使用する必要があります。

DataAnnotationsは通常、クライアント/サーバー側の検証に使用されるため、モデルに別の分離を追加し、アクションViewModelsにを導入しViewModelます。Insert

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とビジネスモデルを明確に分離する必要があります。

于 2012-09-25T14:23:50.143 に答える
1

ASP.NET MVCでは、DTOの一般的な使用法は、ビューモデルと呼ばれるものの一部です。Viewmodelは、1つから複数のDTOを1つのクラスに結合して、ビューの表示とサーバーへの値の投稿用に調整されたクラスです。

あなたがしていることは正しく、問題はありませんが、データ注釈はDTOではなくビューモデルに存在する必要があります。DTOをビューモデルと呼ばない限り、問題ありません。

ASP.NET MVCの世界でのモデル(ドメインモデル)とViewModelに関する次の投稿をお読みください。

お役に立てれば

于 2012-09-25T14:27:56.850 に答える
1

PersonServiceアーキテクチャのドメイン層(またはドメインのすぐ上のアプリケーション層)の一部と見なすことができ、コントローラーとDTOはその上の層にあります。つまり、PersonService署名にDTOへの参照を含めるのではなく、ここでドメインPersonクラスを使用する必要があります。したがって、マッピングコードはコントローラーに入力する必要があります。これにより、ドメインロジックがWebサービスコントラクトの変更の影響を受けないことが保証されます。これは、実際にはを使用する1つの方法にすぎない可能性がありますPersonService。また、具体的なデータアクセスの実装について知る必要がないPersonServiceため、リポジトリに挿入されるインターフェイスも紹介します。PersonService

属性に関して[Required]は、Webサービスメソッドのデータコントラクトを示しているだけなので、DTOにこれを設定しても問題はありません。Webサービスを呼び出す人は、このデータ契約を順守する必要があります。もちろん、この要件は通常、例外をスローするなどして、ドメインコードのどこかに反映されます。

于 2012-09-25T14:44:05.470 に答える
1

[必須]、MaxLength、Rangeなどの注釈をDTOに付けても問題ないと思います。

DTOは、任意の(信頼できない可能性のある)ソース(Webサイトだけでなく、別のエンドポイント、WCFサービスなど)から取得できます。すべての要求はサービス/ビジネスレイヤーに送られるため、ビジネスロジックを実行する前に入力を検証する必要があります(単純なガードチェック)。DTOに注釈を付けると、手元のタスクを実行するために必要な入力を簡単に説明できます。注釈付きのオブジェクトを渡すことは、検証を実行することではありません。

ただし、サービス/ビジネスレイヤーでDTO情報が正しいことを検証する必要があると思います(注釈はこれを確認するための優れた方法です)。

状況についての私の考え:)

于 2015-12-05T14:23:23.420 に答える