エンティティフレームワークが、レイヤー間でデータを転送するために同じプロパティを持つ新しいオブジェクトを作成するロジックを提供しないのはなぜですか?
エンティティフレームワークで生成したエンティティオブジェクトを使用します。
エンティティフレームワークが、レイヤー間でデータを転送するために同じプロパティを持つ新しいオブジェクトを作成するロジックを提供しないのはなぜですか?
エンティティフレームワークで生成したエンティティオブジェクトを使用します。
回答:
それはあなた次第です。
ほとんどの人は、それは良い習慣ではないと言うでしょうが、場合によっては逃げることができます。
EFは複数の理由でDDDをうまく利用できませんでしたが、2つの顕著な点があります。エンティティにパラメーター化されたコンストラクターを持たせることはできず、コレクションをカプセル化することはできません。ドメインモデルにはデータと動作の両方を含める必要があるため、DDDはこれに依存しています。
ある意味で、EFは貧弱なドメインモデルを持つように強制します。この場合、エンティティをDTOとして使用できます。ナビゲーションプロパティを使用すると問題が発生する場合がありますが、それらのエンティティをシリアル化し、ネットワーク経由で送信できます。しかし、実際的ではないかもしれません。送信する必要のないプロパティを持つ各エンティティのシリアル化を制御する必要があります。より簡単な方法は、データ転送用に調整された個別のクラスを単純に設計することです。AutoMapperなどのライブラリは、この目的のために作成されます。
たとえばPerson
、次の定義で呼び出されるクラスがあるとします。
public class Person
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime DateOfBirth { get; get; }
// plus a bunch of other properties relevant about a person
}
あなたがどこかの従業員のリストを表示したいと仮定すると、それだけで送信することが現実的にできるId
、FirstName
とLastName
。ただし、他のすべての無関係なプロパティを送信する必要があります。応答のサイズを気にしない場合、それはそれほど大きな問題ではありませんが、一般的な考えは関連するデータのみを送信することです。一方、人のリストを返すAPIを設計することもできます。その場合、すべてのプロパティの送信が必要になる可能性があるため、エンティティをシリアル化して送信することは理にかなっています。この場合、DTOクラスの作成は議論の余地があります。エンティティとDTOの混在が好きな人もいれば、そうでない人もいます。
更新された質問に答えるために、EFはORMです。その仕事は、データベースレコードをオブジェクトに、またはその逆にマップすることです。EFを通過する前後にこれらのオブジェクトをどうするかは、その懸念の一部ではありません。また、そうすべきではありません。
いいえそうではありません。
理想的には、DTOは永続リポジトリ(別名、データベーステーブル)と一致します。
ただし、ビジネスクラスは必ずしも一致するとは限りません。データベースにあるものに追加のクラス、分離したクラス、または結合したクラスが必要になる場合があります。アプリケーションが小さい場合、この種の問題は実際には見られないかもしれませんが、中規模から大規模のアプリケーションでは、これは頻繁に起こります。
もう1つは、DTOは永続性を扱うもののドメインの一部であり、ビジネスレイヤーはDTOについて何も知らないということです。
実際には非常に悪い考えです。Martin FowlerにはLocal DTOに関する記事があります。
要するに、DTO
Patternは、同じプロセス内のレイヤー間ではなく、ワイヤー経由などでプロセス外にデータを転送するために使用されました。
いいえ、それは悪い習慣です。
いくつかの理由:
@JsonIgnore
Javaの世界など)を使用してフィールドを無視できますが、これは次の問題につながります...get
エンティティのメソッドを呼び出すだけです。このため、エンティティフィールドをDtoにマッピングするために、この作業を支援するために、何らかのマッパーツールを使用する方が簡単で安全です。
@Dherikが言ったことを完了するために、エンティティオブジェクトをデータ転送オブジェクトとして使用する主な問題は次のとおりです。
トランザクションでは、エンティティをDTOとして使用するため、エンティティで行われた変更をコミットするリスクがあります(トランザクションでセッションのエンティティをデタッチできる場合でも、ほとんどの場合、この状態を前に確認する必要があります)エンティティDTOの変更、およびトランザクションを実行していないこと、または変更を保持したくない場合にセッションが閉じられていることを保証します)。
クライアントとサーバー間で共有するデータのサイズ:リクエストの応答のサイズを最小化するために、エンティティのすべてのコンテンツをクライアントに送信したくない場合があります。特定のユースケースで送信するデータを特殊化するために、DTOをエンティティから分離する方がより柔軟です。
可視性とメンテナンス:エンティティのフィールドでjpa / hibernateアノテーションを管理し、同じ場所でjsonでシリアル化するためにjacksonアノテーションを維持する必要があります(継承したインターフェイスに配置する際にエンティティ実装から分離できる場合でも)エンティティ)。次に、新しいフィールドを追加する際にDTOコンテンツを変更すると、他の人はおそらくそれがエンティティのフィールドであると考えることができます。したがって、データベース内のテーブルのフィールドです(@Transient
すべてのDTOフィールドで注釈を使用できる場合でもケースのために..!)。
私の意見では、エンティティを読むときにノイズが発生しますが、私の意見は確かに主観的です。