web-dev-qa-db-ja.com

エンティティフレームワークと貧血ドメインモデルの回避

私たちのビジネスロジックでは、次のようなメソッドが定義されていることがあります。

User.ResetCourse(Course courseToReset)

問題は、ユーザーとコースの両方がEntity Frameworkプロキシオブジェクトであることです。これは、ユーザーまたはコースのいずれかでナビゲーションプロパティをヒットすると、それらのオブジェクトがIQueryableではないため、通常どおり反復するため、データベースに大きなヒットを引き起こす可能性があることを意味します。

これを解決するために、署名を次のように変更しました。

User.ResetCourse(MyDBContext db, Course courseToReset)

つまり、データベースに直接クエリを実行して効率的な方法で必要な変更を加えることができますが、データベースコンテキストをビジネスオブジェクトに渡すのは非常に間違っているようです。

後でユーザーにサービスレイヤーを移行しました。つまり、次のようなものがあります。

CourseService.ResetForUser(Course courseToReset, User forUser)

このサービスには、作成時に注入されたDBContextへの参照がありますが、現在のビジネスオブジェクトは、動作のない単なるデータバッグです(つまり、貧血ドメインモデル)。

どうすればこれを回避できますか?

11
Steve

問題は、そもそもドメインオブジェクトとしてEFオブジェクトを使用していることです。 EFオブジェクトはdata modelsビジネスモデルではありません。

必要に応じて自由に実行できるビジネスオブジェクトを宣言し、リポジトリで取得して保存する必要があります。リポジトリは、EFエンティティをビジネスエンティティにマップします。 EFオブジェクトをリポジトリの外で使用しないでください。

8
TheCatWhisperer

あなたはおそらく次のようなことをすることでそれを避けることができます:

CourseService.prepareForUserCourseReset(DBContext db);
User.reset();
Course.reset();
CourseService.completeUserCourseReset(DBContext db);

とにかく、あなたが私のドリフトをキャッチした場合、とにかくその効果に何か。説明した最初の方法で使用しているアプローチはperformanceに関連しており、必ずしもドメインの構造に関連しているわけではないようです。したがって、実際にはサービス層でパフォーマンスの問題を解決することを検討する必要がありますが、ドメイン内の動作は維持できます。より適切な回答が必要な場合は、このコンテキストでユーザー/コースをリセットすることの意味も知っておくと役立ちます。

0
RibaldEddie