0

我经常遇到 MVC 中的模型设计问题。大多数情况下,我的所有项目都需要一些要创建、编辑和删除的实体。这些实体中的大多数都有一些共同的属性,如创建日期、修改日期、作者、修改者,在某些情况下甚至更具描述性的属性是常见的。因此,我有一个单独的数据库表来存储它们。例如,文档表,我们在其中存储发票、报价单和其他业务文档。我正在为 ORM 使用 Entity Framework v4,我们最终得到了 Document 实体。

如何修改此实体,或者为它创建一个单独的 DocumentViewModel 类以支持具有公共属性的多种文档类型(因此应该实现某种形式的继承或接口实现)?除了识别不同的文档类型外,我还需要一些类型来拥有不同的数据注释规则(属性)。

例如,Document 表有 PayDate 列。文档类型 Invoice 需要提供 PayDate,但文档类型 Quotation 不需要。

这是我在使用 MVC 时一遍又一遍地面临的一个问题,到目前为止,我每次都在处理不同的问题,但无法决定如何正确处理它以实现最大的应用程序可维护性和易于开发。

4

2 回答 2

2

您是否考虑过使Documents实体抽象

从 DB 端,您将拥有Documents表,其中仅包含所有 Invoices/Quoations/etc 共享的字段。该字段将有一个 IDENTITY PK - 例如 DocId。

在其他表中,可以存储特定于该文档的附加元数据,并且 PK 是(非 IDENTITY)字段 DocId,它也是Documents表的 FK。

在 EF 端,Documents成为一个抽象实体,其他实体继承自该实体。这允许存在一个很好的 OO 范例,并使您的代码更加健壮。

我们目前正在使用这种方案(EF4/SQL Server)。

您的场景听起来与我们的非常相似 - 考虑使用抽象类。

编辑

以为我会为我实际实现此场景的方式添加更多信息,以使您走上正确的轨道。

由于对您的 Q 状态的评论,我们对您的领域知之甚少,因此很难做出明智的意见。就个人而言,我选择让我的实体抽象,因为某些功能需要一个“混合包”的项目才能一次返回。当然还有其他方法可以做到这一点(例如存储过程),但这允许在我的 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);

踢球者是我的存储库是用泛型实现的,类型参数确保类型安全:

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。现在添加另一个,并将其命名为 Quotation... 在 Quotation 上,单击 PayDate 并按删除键。您可以根据需要自定义这些!你可以对其他 ORM 做同样的事情,只是需要做更多的工作。使用 NHibernate,您将手动创建模型,然后将它们映射到同一个表,但只映射您需要的内容。

于 2010-10-05T22:33:39.197 回答