开发者

Model design in ASP.NET MVC

开发者 https://www.devze.com 2023-01-19 07:18 出处:网络
I am constanstly having problems with model design in MVC. Mostly all of my projects require some entities that are to be created, edited and deleted. Most of these entities have some common propertie

I am constanstly having problems with model design in MVC. Mostly all of my projects require some entities that are to be created, edited and deleted. Most of these entities have some common properties like creation date, modified date, author, modified by and in some cases even more descriptive properties are common. Because of that I have one single DB table to store them. For instance, Documents table and we store Invoices, Quotations and other business documents in it. I am using Entity Framework v4 for ORM, where we eventually end up with the Document entity.

How do I modify this entity or do I create a separate DocumentViewModel class for it to support multiple document types with common properties (so some form of inheritance or interface implementation should be implemented)? Besides identifying different document types I also need to have some types to have different Data Annotation rules (attributes).

For instance, Document table has PayDate column. Document type Invoice requires PayDate to be provided but document type Quotation does not.

This is the one single problem I am facing over and over with MVC and so far I've been handling it different every ti开发者_JAVA技巧me but cannot decide how to properly handle it to achieve the maximum application maintainability and ease of development.


Have you considered making Documents entity abstract?

From the DB side, you will have Documents table containing just the fields shared by all Invoices/Quoations/etc. This field will have an IDENTITY PK - e.g DocId.

In the other tables, additional meta-data specific to that document can be stored, and the PK is a (non-IDENTITY) field DocId, which is also a FK to the Documents table.

On the EF side, Documents becomes an abstract entity, and the other entities inherit from this entity. This allows a nice OO paradigm to exist, and makes your code more robust.

We are currently using this scheme (EF4/SQL Server).

Your scenario sounds very similar to ours - consider using Abstract Classes.

EDIT

Thought i'd add a bit more info to how i've actually implemented this scenario, to put you on the right track.

As the comments to your Q state, we have little knowledge of your domain, therefore it's hard to make informed opinions. Personally, i chose to make my entity abstract, because certain functionality required a "mixed-bag" of items to be returned in one hit. There are other ways to do this of course (such as a stored procedure), but this allows a nice fluent interface between my UI (which is MVC by the way) and my service layer.

Works like this - here's how i get a single Post:

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

Here's how i get a mixed-bag of Posts:

// 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"); 

Here's how i get a collection of "Reviews" (child of Post):

// 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);

The kicker is my repository is implemented with generics, and the type parameter ensures type-safety:

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

And it's implemented like this:

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

The OfType causes an inner join to the T (which is the child table), so only those records are returned.

Of course, i also have a service layer mediating between my UI and repository, but this should get you on the right track.

Also, you don't have to go with the whole Expression-predicate thing, i like this because it minimizes the number of methods on my interface, and gives full querying power to my controllers, whilst ensuring the queries are deferred to the point of the service layer, but not further.

If you don't like this, you could of course have regular parameters (string title, etc).

As i said, this architecture suited my domain requirements, so it may not necessarily suit yours, but hopefully it gives you some insight.


You can put a table in your EF model many times and just rename them to the entities you need. Just delete the columns you dont need from those.

For example, put in a Documents entity... now rename it to Invoice. Now add another one, and name it Quotation... on the Quotation, click on PayDate and hit the delete key. You can customize these all you want! You can do the same with other ORMs, just takes a little more work. With NHibernate you would manually create the Models, then map them to the same table, but only map what you need.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号