56

Entity Frameworkの使用を開始したばかりですが、ビジネスレイヤーのクラスが、EntityFrameworkによって作成されたエンティティにどのように適合するかについて混乱しています。

従来のADO.NETを使用する場合、たとえばCustomerというクラスがあり、次にデータベースの相互作用を処理するDALCustomerという別のクラスがあります。この構造では、DALのインスタンスを計算、フィルタリング、および削除するためのコードを配置します。 Customerクラスで保存、更新、および削除するためのCustomer。

Entity Frameworkを使用すると、Customerというテーブルがある場合、Entity FrameworkはCustomerというエンティティを作成します。これが私の混乱の始まりですが、このエンティティはビジネスレイヤーでのCustomerの必要性を排除しますか?では、本質的に、通常はビジネスレイヤーにあるすべてのフィールドとメソッドは、EntityFrameworkによって生成されたエンティティに含まれるのでしょうか。または、たとえばCustomerBLと呼ばれるビジネスレイヤーに、計算、フィルタリングに必要なビジネスロジックを実行するために必要なフィールドとメソッドが含まれ、データアクセスを処理するために宣言されたEF DALのインスタンスが必要なクラスがまだ存在する必要がありますか?

ビジネスクラス(この場合はCustomerBL)が必要な場合、もう1つの質問が頭に浮かびます。これは、顧客エンティティで作成されたフィールドをCustomerBLで再作成するか、顧客エンティティのインスタンスをCustomerBLで宣言して、 2つの場所でフィールドを宣言する必要はありませんか?

4

5 に答える 5

27

エンティティフレームワークは、データモデルと概念モデルの分離を念頭に置いて設計されました。継承エンティティ分割(EFコアではない)、テーブル分割複合型または所有型、および透過的な多対多の関連付け(EFコアではない)をサポートします。これらはすべて、制約を受けることなくドメインモデルをニーズに合わせて成形できます。データストアモデルによるものです。EFコアは、公開されたクラスモデルから横断的関心事を隠すために使用できるシャドウプロパティをサポートします。

コードファーストアプローチでは、少数のプロパティのみがデータストア列にマップされ、他のプロパティがドメインの目標を達成するPOCOを操作できます。モデルファーストとデータベースファーストは部分クラスを生成し、生成されたコードを拡張できるようにします。

もちろん、この概念モデルと店舗モデルの分離は、ある程度成功するだけです。永続性の無知というこの目標に反するものもあります。例えば ​​-

  • 遅延読み込みが必要な場合は、ナビゲーションプロパティをとして宣言する必要がありvirtualます。これにより、EFはプロキシタイプでそれらをオーバーライドできます。ドメイン駆動設計(DDD)はvirtual、ポリモーフィズムが必要な場合にのみ使用することを推奨します。

  • 「実際の」関連付け(参照)に付随するプリミティブ外部キープロパティ(たとえば)があると非常に便利です。純粋主義者はこれをDDDの原則に違反していると考えています。ParentIdParent

  • EFクラスモデルはデータアクセス層の一部であり、主にその目標を果たす必要があります。したがって、LINQクエリを作成するときにナビゲーションプロパティを最大限に活用するために、多くの相互関係が含まれます。これらの相互関係は、DDDの原則に対するもう1つの違反です。

  • LINQ-to-objectsとLINQ-to-entitiesの間には多くの違いがあります。メモリ内のオブジェクトとはまったく異なるユニバースに対してLINQを実行しているという事実を無視することはできません。これは、密結合またはリーク抽象化と呼ばれます。

  • EFは具象クラスのみをマップでき、インターフェースはマップできません。

しかし、それでは...一般的に、コードファーストモデルから生成されたEFクラスまたはPOCOをドメインクラスとして使用することに満足しています。これまでのところ、あるデータストアまたはORMから別のデータストアへの摩擦のない移行は、たとえ起こったとしても見たことがありません。永続性の無知はフィクションです。DALからの特異性は、ドメインにフットプリントを簡単に残します。さまざまなデータストア/モデルをコーディングする必要がある場合、またはストア/モデルが比較的頻繁に変更されることが予想される場合にのみ、このフットプリントを可能な限り最小化するか、完全に抽象化することが効果的です。

ドメインクラスとしてEFクラスを促進する可能性のある別の要因は、今日の多くのアプリケーションに複数の層があり、(シリアル化された)異なるビューモデルまたはDTOがクライアントに送信されることです。UIでドメインクラスを使用することは、ほとんど問題になりません。ドメインとしてEFクラスモデルを使用し、UIまたはサービスコンシューマーの要求に応じてサービスに専用モデルとDTOを返すようにすることもできます。別の抽象化レイヤーは、パフォーマンスの面でのみではあるが、祝福よりも負担が大きい場合があります。

于 2013-01-15T20:05:28.597 に答える
15

私の意見では、永続化できるエンティティとしてPOCOを使用することの全体的なポイントは、「データベースエンティティ」と「ビジネスエンティティ」の区別を取り除くことです。「エンティティ」は、データストアに直接永続化およびロードできる「ビジネスエンティティ」であると想定されているため、同時に「データベースエンティティ」として機能します。POCOを使用することにより、ビジネスエンティティは、データベースと対話するための特定のメカニズムから切り離されます。

エンティティを別のプロジェクト(たとえば、EFアセンブリへの参照がない)に移動し、データベースレイヤープロジェクトでそれらを使用して永続性を管理できます。

これは、EFの要件を考慮せずにビジネスエンティティを完全に設計できることを意味するものではありません。たとえば、EFを使用してビジネスエンティティをデータベーススキーマにマッピングする際に問題を回避するために知っておく必要のある制限があります。

  • virtualEFでの遅延読み込みをサポートするには、ナビゲーションプロパティ(他のエンティティへの参照または参照のコレクション)を作成する必要があります
  • IEnumerable<T>永続化する必要のあるコレクションには使用できません。ICollection<T>それ以上の派生型である必要があります。
  • privateプロパティを永続化するのは簡単ではありません
  • このタイプcharはEFでサポートされていないため、値を保持する場合は使用できません。
  • もっと...

しかし、追加のエンティティのセットは、私の意見では、上記の制限がプロジェクトに対して厳しすぎる場合に本当に必要とされることを正当化する必要がある複雑さの追加の層です。

YA2C(さらに2セント:))

于 2013-01-15T20:16:46.073 に答える
5

他の人が良い習慣と見なしているかどうかはわかりませんが、個人的には、これは私が過去にこれをどのように処理したかです:

EF によって生成されたクラスは DAL であり、BL の場合は、必要な構造 (関連するエンティティからのデータを 1 対 1 の関係でマージするなど) を持つ補完的なクラスのセットを作成し、その他のビジネス ロジックの問題が処理されます。 (たとえば、IDataErrorInfo を実装して WPF の UI とうまく連携させるようなカスタム検証)、また、BL インスタンスを使用し、EF エンティティとの間で変換する、エンティティのタイプに関連するすべてのビジネス層メソッドを含むクラスを作成します。 BLオブジェクトに。

したがって、たとえば、データベースに Customer があります。EF はクラス Customer を生成し、BL には Customer (プレフィックス、サフィックスなど) クラスと CustomerLogic クラスがあります。BL Customer クラスでは、EF エンティティを改ざんすることなく、要件を満たすために必要なことは何でも行うことができます。CustomerLogic クラスでは、BL メソッド (最も重要な顧客をロードする、顧客に余分なデータを保存するなど) があります。

これで、データソースの実装に疎結合できるようになりました。過去に (WPF プロジェクトで) これが私に利益をもたらしたもう 1 つの例は、IDataErrorInfo を実装し、CustomerBL クラスに検証ロジックを実装して、エンティティを UI の作成/編集フォームにバインドするときに実行できることです。 WPF が提供する組み込み機能を利用できます。

...私の 2 セント、私はベスト プラクティスとは何か、または他のソリューション/視点は何かを知りたいと思っています。


おそらくこのトピックにも関連しています-コードファーストとモデル/データベースファースト

于 2013-01-15T18:06:35.127 に答える
3

このトピックは少し古いかもしれませんが、これが役立つかもしれません。Andras Nemes は彼のブログで、EF や MVC などのテクノロジー駆動型設計よりも DDD (ドメイン駆動型設計) を使用することの懸念を指摘しました。

http://dotnetcodr.com/2013/09/12/a-model-net-web-service-based-on-domain-driven-design-part-1-introduction/

于 2014-03-28T13:11:05.017 に答える