ASP.NET MVCアプリケーションは、Entity Frameworkをモデルとして直接使用する必要がありますか?


22

私はVisual Studio 2013(MVC 5)で最初のMVCアプリケーションを構築していますが、モデルをセットアップする最適な方法については少しわかりません。

既存のデータベースからコードファーストを使用して、エンティティフレームワークモデルを生成しました。私の最初の本能は、ビューで使用されるモデルとなるいくつかの中間クラスを作成し、それらのクラスをエンティティフレームワーククラスと連携させることでした。

中間クラスを書いているとき、EFクラスがたまにプライベートセッターで行ったり、あるデータ型から別のデータ型にキャストしたりすることの多くを再実装していることに気付きました。それは無駄のように思えた。

エンティティフレームワーククラスをMVCアプリケーションのモデルとして直接使用するという一般的な規則はありますか?または、これらの中間クラスを構築するのに欠けている利点がありますか?


1
このかもしれないのヘルプ:programmers.stackexchange.com/questions/123011/...
oasten

コードファーストを使用している場合、既存のデータベースはありませんでしたか?
アイザッククラインマン14年

1
EF 6.1+では、既存のデータベースからコードファーストモデルを生成できます。このMSDN記事を参照してください
マイクD. 14年

回答:


23

私のアプリケーションでは、データベース(Entity Framework)とMVCの異なるモデルを使用して、常に物事を分離しています。私もこれらを異なるプロジェクトに分けました。

  • Example.Entities -EFのエンティティとそれらにアクセスするためのDBコンテキストが含まれています。
  • Example.Models -MVCモデルが含まれています。
  • Example.Web -Webアプリケーション。Example.DomainとExample.Modelsの両方に依存します。

ドメインエンティティのように他のオブジェクトへの参照を保持する代わりに、MVCモデルはIDを整数として保持します。

ページのGETリクエストが到着すると、MVCコントローラーはデータベースクエリを実行し、エンティティを返します。ドメインエンティティを取得し、MVCモデルに変換する「コンバーター」メソッドを作成しました。(MVCモデルからドメインエンティティまで)反対のことを行う他の方法があります。その後、モデルはビューに渡され、クライアントに渡されます。

POSTリクエストが到着すると、MVCコントローラーはMVCモデルを取得します。コンバーターメソッドは、これをドメインエンティティに変換します。このメソッドは、属性として表現できない検証も実行し、ドメインエンティティが既に存在する場合、新しいエンティティを取得するのではなく、更新することを確認します。通常、メソッドは次のようになります。

public class PersonConverter
{
    public MyDatabaseContext _db;

    public PersonEntity Convert(PersonModel source)
    {
         PersonEntity destination = _db.People.Find(source.ID);

         if(destination == null)
             destination = new PersonEntity();

         destination.Name = source.Name;
         destination.Organisation = _db.Organisations.Find(source.OrganisationID);
         //etc

         return destination;
    }

    public PersonModel Convert(PersonEntity source)
    {
         PersonModel destination = new PersonModel()
         {
             Name = source.Name,
             OrganisationID = source.Organisation.ID,
             //etc
         };

         return destination;
    }
}

これらの方法を使用することにより、そうでなければ各コントローラーで発生する重複を取り除きます。ジェネリックを使用すると、さらに重複を排除できます。

このように物事を行うことには、複数の利点があります。

  • 特定のビューまたはアクションに合わせてモデルをカスタマイズできます。送信すると、多くの異なるエンティティ(個人、組織、住所)を作成する個人のサインアップフォームがあるとします。別のMVCモデルがなければ、これは非常に困難です。
  • エンティティでのみ使用できる情報よりも多くの情報をビューに渡す必要がある場合、または2つのエンティティを単一のモデルに結合する必要がある場合、貴重なデータベースモデルは変更されません。
  • MVCモデルをJSONまたはXMLとしてシリアル化する場合、このモデルにリンクされている他のすべてのエンティティではなく、シリアル化されている直接のモデルのみを取得します。

良い答えは、あるクラスから別のクラスにプロパティを手動でマッピングする代わりに、ValueInjectorまたは類似のもの(個人的にはオートマッパーが嫌いです)を使用することをお勧めします。
ロックラン14

1
個別の回答を追加するのではなく、DDDプラクティスでは、ビューの「コンバーター」と個別のモデルがアプリケーションサービスレイヤーの一部と見なされることをここでコメントします。基本的に、アプリケーションからその複雑さを隠しながら、ドメインモデルを必要に応じて複雑にすることができます。また、ドメインモデルの変更のためにアプリケーションを変更する必要がないようにします。ASLが翻訳を処理します。
マイケルブラウン14年

そのため、PersonModelにある各モデル(Organizationオブジェクト)を呼び出して、そのモデルの情報を取得しますか?個人と組織の情報を更新するフォームがあるとします。組織を更新するときに追加の電話がありますか?ストアドプロシージャを使用しているので、モデルのすべての属性と含まれるモデルの属性を一度に送信できませんでしたか?
明るい

1
コレクションのマッピングをどのように処理しますか?それは...これだけですべてを再作成として、あなたは、もはやただの更新を持つエンティティの新しいリストを作成することができますようはるかEF6に複雑されていないようだ
ジェラルド・ウィルキンソン

2
独自のコンバータクラスを記述する代わりに、この問題に対処するために記述されたAutomapperライブラリを使用することをお勧めします。2014年以来、かなり成熟しています!
ベンスミス

6

私はそれが本当にあなたのアプリケーションに依存すると言うでしょう。ビジネスロジックなしで、純粋なCRUDを実行するだけですか?次に、EFモデルをビューで直接使用します。

ほとんどの場合、少なくともいくつかのビジネスロジックが関係するため、データ/ EFモデルとビューの間にレイヤーを配置することをお勧めします。この場合、「CQRS-lite」(以下を参照)を実行し、コントローラーの内外で異なるモデルを使用するのが適切かもしれません。ほとんどの場合、読み取りモデルは書き込みモデルよりも「太い」です...

ただし、アプリケーションに多くのビジネスロジックが含まれている場合、および/または多くのスケーリングが必要な場合は、CQRS(コマンドクエリの責任分離)、DDD(ドメインドリブンデザイン)、および場合によってはイベントソーシングを使用して、少なくともそのコアを実装します。次に、EFを読み取りモデルのファサードとして使用できます。

また、アプリケーション全体で1つの戦略/パターンに固執する必要はありません。一部の領域は純粋なCRUDであり、他の領域には多くのビジネスロジックが含まれている可能性があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.