web-dev-qa-db-ja.com

アプリケーションのどの層にDTO実装を含める必要があるか

最近、DTOとその有用性について多くのことを聞いてきましたが、ASP.NETコンテキストで使用する良い例が見つかりません。

私が3層アーキテクチャを使用しているとしましょう:

  1. データレイヤー(Entity Frameworkを使用)
  2. ビジネス層(WCFサービス)
  3. プレゼンテーションレイヤー(MVC 4.0 Webアプリケーション)

EF EmployeeオブジェクトからEmployeeDTO POCOにどこで変換する必要がありますか?

データアクセスレイヤーで変換を行いますが、WCFサービスではどうなりますか?次に、別のDataMemberオブジェクトに変換し、UIレイヤー(MVC Webアプリ)に到達したら、3回目にモデルに変換する必要がありますか?誰かが私のためにこれをクリアしていただければ幸いです

23
Denys Wessels

同様の状況で、私はdtoをCoreに入れていました。これは3つすべてに知られています。だからあなたは

コア
 | 
 ------------ 
 | | | 
 DAL BL PL 

各レイヤーはCore.Dto.Employeeで操作できます。各レイヤーはまた、そのAPIでCore.Dto.Employeeを外部に公開します。しかし内部的には、各レイヤーはCore.Dto.Employeeを変換/適応できます。データベースEF.Employeeから読み取り、後でCore.Dto.Employeeに変換します。変換はレイヤーの境界に含まれます。

レイヤー全体で同じものを表すいくつかの異なるモデルがある場合、たとえばPLがPL.Employeeを必要とし、DALがEF.Employeeで動作する場合、混乱を招きます。

7
oleksii

サービス層はDTOを公開します。これは、サービスレイヤーでデータコントラクトを定義して、外部に公開したいということを意味します。ほとんどの場合、それらはフラット化されたエンティティであり、必ずしもデータベースエンティティと同じ構造である必要はありません。

ビジネス/データレイヤーを使用し、外部に公開するDTOを構築するのは、サービスレイヤーの責任です。

ビジネスレイヤーとデータレイヤーで何を使用するかは、アーキテクチャによって異なります。最初にコードでマップされるドメインモデルを使用できます。その場合、サービス層はドメインエンティティをデータコントラクト(DTO)にマップします。ドメインモデル(貧血モデル)がない場合は、データベースを直接DTOにマップすることもできます。

ASP.NET MVCサイトはサービスを利用し、受け取ったDTOを専用のビューモデルにマッピングして、特定のビューに渡されます。

さらに、クエリをコマンドから分割することもできます。クエリの結果として返されるDTOは、サービスに送信するコマンドとはまったく異なるため、これは良いアプローチです。コマンドには、コマンドの実行に必要なものだけが含まれ、ビジネスの目的は達成したいものを含みますが、クエリは、UIで必要なもののフラット化されたモデルを返します。

その他の備考:

  • データベースエンティティを公開しないでください。
  • ビジネスロジックではないため、ビジネスレイヤーで変換しないでください。
8
L-Four

コメントを追加するのに十分な評判がないため、ここに追加された https://stackoverflow.com/a/6310507/1771365 をご覧ください。

個人的には、永続層とビジネス層の間でエンティティを渡します。 MVCを使用しているので、ビューモデルをコントローラーに渡す可能性があります。その時点で、ビューモデルをDTOにマップします。

すべてのレイヤー間でDTOを使用することを計画している場合は、参照できる横断的プロジェクトを作成します。

3
Stig

私が特に気に入っているアプローチは、ビジネスレイヤーでのDTO変換です。

シナリオ:プレゼンテーション層がビジネス層を呼び出し、DTOを渡します。ロジックと検証を行ってから、DTOをエンティティに変換し、データアクセスレイヤーに送信します。

UI->バス。レイヤー(エンティティに変換)->データレイヤー

データレイヤーには変換ロジックがなく、必要に応じてエンティティを受け取って処理する必要があると思うので、このアプローチが好きです。これが効果的であるもう1つの理由は、データレイヤーに送信する前に、変換プロセス中に特定のビジネスルール/検証ロジックを定義できるようになったことです。これは古い MSDN記事 ですが、同様のアプローチを説明する詳細がいくつかあります。

1
Niels Filter

私はそのような目的のためにSharedという名前のプロジェクトを使用し、具体的にはすべてのレイヤーとオブジェクトを共有します。名前に関係なく、すべてのレイヤーで表示できます。

1
user3021830