0

MVCでのモデル設計に常に問題があります。ほとんどすべてのプロジェクトで、作成、編集、削除するエンティティが必要です。これらのエンティティのほとんどには、作成日、変更日、作成者、変更者などの一般的なプロパティがあり、場合によってはさらに説明的なプロパティが一般的です。そのため、それらを格納するための単一のDBテーブルがあります。たとえば、Documentsテーブルには、請求書、見積もり、その他のビジネスドキュメントが保存されます。ORMにEntityFrameworkv4を使用していますが、最終的にはDocumentエンティティになります。

このエンティティを変更するにはどうすればよいですか、または共通のプロパティを持つ複数のドキュメントタイプをサポートするために別のDocumentViewModelクラスを作成するにはどうすればよいですか(したがって、何らかの形式の継承またはインターフェイスの実装を実装する必要があります)。さまざまなドキュメントタイプを識別することに加えて、さまざまなデータ注釈ルール(属性)を持つためにいくつかのタイプも必要です。

たとえば、ドキュメントテーブルにはPayDate列があります。ドキュメントタイプの請求書ではPayDateを指定する必要がありますが、ドキュメントタイプの見積もりでは指定できません。

これは、MVCで何度も直面している単一の問題であり、これまでは毎回異なる方法で処理してきましたが、アプリケーションの保守性と開発のしやすさを最大限に高めるために、適切に処理する方法を決定できません。

4

2 に答える 2

2

Documentsエンティティを抽象化することを検討しましたか?

DB側からは、すべての請求書/見積書などで共有されるフィールドのみを含むドキュメントテーブルが作成されます。このフィールドにはIDENTITYPK(DocIdなど)が含まれます。

他のテーブルでは、そのドキュメントに固有の追加のメタデータを保存できます。PKは(非IDENTITY)フィールドDocIdであり、DocumentsテーブルのFKでもあります。

EF側では、Documents抽象エンティティになり、他のエンティティはこのエンティティから継承します。これにより、優れたOOパラダイムが存在し、コードがより堅牢になります。

現在、このスキーム(EF4 / SQL Server)を使用しています。

あなたのシナリオは私たちのシナリオと非常によく似ています-抽象クラスの使用を検討してください。

編集

あなたを正しい軌道に乗せるために、私が実際にこのシナリオをどのように実装したかについてもう少し情報を追加したいと思いました。

あなたのQ状態へのコメントとして、私たちはあなたのドメインについてほとんど知識がないので、情報に基づいた意見を述べるのは難しいです。個人的には、エンティティを抽象化することを選択しました。これは、特定の機能では、アイテムの「混合バッグ」を1回のヒットで返す必要があるためです。もちろんこれを行う方法は他にもありますが(ストアドプロシージャなど)、これにより、UI(ちなみにMVC)とサービスレイヤーの間の優れた流暢なインターフェイスが可能になります。

このように機能します-これが私が単一の投稿を取得する方法です:

// var is strongly-typed to a "Post"
var somePost = repository.FindSingle(10); 

投稿の混合バッグを取得する方法は次のとおりです。

// var is strongly-typed to a "ICollection<Post>".
// "Title" is a property on my "Post" abstract POCO
var mixedBagOfPosts = repository.FindAll<Post>(p => p.Title = "Some Title"); 

「レビュー」(投稿の子)のコレクションを取得する方法は次のとおりです。

// var is strongly-typed to a "ICollection<Review>"
// "Rating" is a property on my "Review" POCO (derived from Post)
var reviews = repository.FindAll<Review>(r => r.Rating == 5.00);

キッカーは私のリポジトリがジェネリックスで実装されており、typeパラメーターが型の安全性を保証します。

ICollection<T> FindAll<T>(Expression<Func<T,bool>> predicate) where T : Post

そしてそれはこのように実装されています:

return myContext.Posts.OfType<T>.Where(predicate).ToList();

OfTypeにより、T(子テーブル)への内部結合が発生するため、これらのレコードのみが返されます。

もちろん、UIとリポジトリの間を仲介するサービスレイヤーもありますが、これで正しい方向に進むはずです。

また、式述語全体を使用する必要はありません。これは、インターフェイス上のメソッドの数を最小限に抑え、コントローラーに完全なクエリ機能を提供すると同時に、クエリがサービス層ですが、それ以上ではありません。

これが気に入らない場合は、もちろん通常のパラメーター(文字列タイトルなど)を使用できます。

私が言ったように、このアーキテクチャは私のドメイン要件に合っていたので、必ずしもあなたのドメイン要件に合っているとは限りませんが、うまくいけば、それはあなたにいくつかの洞察を与えるでしょう。

于 2010-10-05T22:49:46.640 に答える
0

EFモデルにテーブルを何度も配置し、必要なエンティティに名前を変更するだけです。不要な列を削除するだけです。

たとえば、Documentsエンティティを挿入します...名前をInvoiceに変更します。次に、別の1つを追加し、Quotation ...という名前を付けます。Quotationで、PayDateをクリックして、Deleteキーを押します。あなたはこれらをあなたが望むすべてをカスタマイズすることができます!他のORMでも同じことができますが、もう少し作業が必要です。NHibernateを使用すると、モデルを手動で作成してから同じテーブルにマップしますが、必要なものだけをマップします。

于 2010-10-05T22:33:39.197 に答える