2012-07-20 44 views
4

我是新来的整个ASP世界,我通过构建一个C#MVC3/EF4项目让我的脚湿了。我发现很难避免在我的模型中复制一堆代码并查看模型。考虑一个对象Foo。我需要用Foo做以下事情:架构:避免MVC /实体框架项目中重复的模型/模型视图代码

  1. 在我的数据库中存储Foo类型的记录。
  2. 允许用户查找单个Foo的记录(将Foo的实例传递给视图)。
  3. 允许用户创建Foo的新实例(将Foo的实例传递给表单)。

比方说,我也有一个类型栏。一个酒吧包含一个Foos列表。这里有两个要求:

  1. 用户可以查看酒吧列表。
  2. 当用户点击一个特定的栏时,它会显示它的所有Foos。

所以,我的基本对象的素描像这样:

class Foo 
{ 
    string FooName; 
    int Id; 
} 

class Bar 
{ 
    List<Foo> FooList; 
    int Id; 
    string Baz; 
} 

但是,当我开始思考不同的看法,它开始变得混乱:

  • 的意见不该没有任何数据成员的写权限。
  • 有一个视图需要一个酒吧列表,但不关心Bar.FooList。比方说,我也想要善于管理资源并尽快关闭DbContext(即在对象存储在内存中但在呈现视图之前)。如果我只是通过一个Bars列表并且设计者试图错误地访问FooList,我们会得到一个运行时错误。呸!

好吧,我只是创建一个独特的ViewModel为每个视图,只读数据成员,没有问题。

  • 然而无论是数据库模型和形式模型将需要连接DataAnnotations这不能不说这是必填字段,字符串等的最大长度。如果我创建单独的形式模型和数据库模型,然后我最终复制所有这些注释。呸!

所以,这是我的架构困境:我想要有简洁的视图模型,它将视图限制为仅读取他们应该访问的数据。我想避免重复数据注释到处。我希望能够尽快释放我的数据库资源。什么是实现我的目标的最佳方式?

回答

0

我的建议是不要在您的EF实体类中使用数据注释。相反,尝试流畅的API。它将模型类本身的持久性问题保留下来。你甚至可以在一个完全不同的库中定义模型构建器的东西。

至于有重复的属性,属性是便宜:

public string MyProp { get; set; } 

不是很多代码,你可能会开始看到的的ViewModels和实体不必总是彼此的确切的重复。例如,如果您想将[HiddenInput]应用于视图模型,使其呈现为<input type="hidden" />?你会将它应用于实体吗?为什么?它属于viewmodel(命名空间甚至是System.Web.Mvc,而不是System.ComponentModel.DataAnnotations)。

至于在验证过程中复制错误消息(如果您单独验证MVC和EF层),则可以使用resx资源。

至于释放数据库资源,让EF管理。我发现每个HttpContext最好保留一个DbContext实例。你可以使用工厂,OnActionExecuting操作过滤器,Application_BeginRequest,IoC容器或其他任何东西来打开它。然后在OnResultExeed,Application_EndRequest等处理上下文。保持简单。

+0

感谢您的回复!我同意像HiddenInput这样的东西不属于实体。但是对于数据库和表单都适用的属性呢,比如MaxLength呢? – 2012-07-20 17:07:14

+0

我使用流畅的API,所以我决不会把maxlength属性放在实体类上。相反,我会在OnModelCreating期间在实体属性上调用'.HasMaxLength(int)'。我不再对视图模型使用数据注解,现在选择FluentValidation。但是,通过让这两个图层的公共共享文件具有类似'public const int MyPropertyLength = 140;'的类型的值,可以保持这两个图层之间的长度属性一致。然后EF和MVC都可以在属性,方法调用,消息等等中引用该const。 – danludwig 2012-07-20 17:18:40

+0

我不明白如何使用EF Fluent API帮助您进行DRY?您仍然必须在EF模型和ViewModel上定义'MaxLength'(例如),否则模型状态将不会自动填充正确的错误以发回给用户。我在这里面对同样的挑战。我知道'BindAttribute',但我不喜欢使用基于字符串的东西。 – 2016-06-16 15:26:51