web-dev-qa-db-ja.com

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

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

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

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

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

23
Mike D.

私のアプリケーションでは、データベース(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つのエンティティを1つのモデルに結合する場合、貴重なデータベースモデルに手を加えることはありません。
  • MVCモデルをJSONまたはXMLとしてシリアル化した場合、シリアル化されている直接のモデルのみが取得され、このモデルにリンクされている他のすべてのエンティティは取得されません。
23
Jack Scott

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

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

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

また、アプリケーション全体で1つの戦略/パターンに固執する必要がないことも覚えておいてください。一部の領域は純粋なCRUDであり、他の領域には多くのビジネスロジックが含まれる場合があります...

6
jhdrn