我正在使用EF-CodeFirst从我的Poco对象及其配置创建数据库。 我大量使用Dataannotation(必需,DataLength,RegularExpression,DataType)来获取MVC的元数据,并将错误消息指向一个资源,以便稍后对它们进行本地化。
对于简单的CRUD操作,这不是问题。
但是只要我需要ViewModel类,我就会从Poco对象中删除Dataannotations。
如何将这2个设计合并而不必伤害DRY(不要重复自己)原则?
由于 安德烈亚斯
答案 0 :(得分:4)
这两种设计不能也不应该结合起来。您的视图模型与视图相关联,因此我个人在视图模型上重新定义了所有必要的属性,并且信不信由我在这种情况下不关心DRY。我这样做是因为我的观点的要求经常变化(是的,客户是反复无常的),而我总是重用相同的域模型。对我来说,一个观点永远不应该知道域模型的存在。视图应该是虚拟的,它应该知道的是视图模型,它由控制器传递给它。
我知道有些人可能会有所不同,我尊重他们的意见。因此,通过这样说,我只是暴露了我的个人观点和我使用ASP.NET MVC的方式。老实说,我的模型是没有任何DataAnnotations的POCO对象,所以我不会遇到这样的问题。我在视图模型上使用DataAnnotations仅用于格式化(DataType
,DisplayName
和DisplayFormat
等内容)并且没有验证属性。我为此目的使用FluentValidation.NET。
答案 1 :(得分:2)
你可以很容易地完成你的要求。达林有一个非常有效的观点,适用于较大的项目,但我认为对于较小的项目,它听起来有点过分。它似乎在很大程度上取决于您是否使用DataAnnotations进行验证或使用第三方库。恕我直言,不这样做的重复将导致相当大的维护麻烦。还有一个事实是,您只需将数据从数据库复制到视图模型就可以使用大量代码。 ORM应该有助于消除这种情况,但到目前为止,解决方案看起来并不是很好。
这是一个关于如何做你想做的代码的示例。第一类是部分的,主体在EF生成的代码中(我先是模型,而不是代码优先)。另外,作为一个例子,Question有一个FK到QuestionGroup。在DB中,这是一个名为GroupID的列,但在ViewModel中有一个名为GroupName的属性,用于显示一个漂亮的小网格(实际上,Telerik网格,如果你尝试传入EF对象,它基本上会中断)。 / p>
[MetadataType(typeof(QuestionMetadata))]
public partial class Question
{
}
public class QuestionMetadata
{
public Int32 ID { get; set; }
[Required]
[Display(Name="Question")]
public String QuestionText { get; set; }
[Display(Name = "Order")]
public Int16 SortOrder { get; set; }
}
[MetadataType(typeof(QuestionMetadata))]
public class QuestionViewModel
{
/* Fields found in the original model */
public Int32 ID { get; set; }
public String QuestionText { get; set; }
public Int16 SortOrder { get; set; }
/* Fields that map child object data for this view model */
[Display(Name = "Question Group")]
public String GroupName { get; set; }
}
恕我直言,EF和Telerik都迫使我在这里不会很干,但我无能为力。 EF应该默认生成这些DataAnnotations(或者至少有选项),因为它显然知道哪些字段是必需的(非空)或者各种字符串的最大长度是多少。然后Telerik强迫我创建ViewModel,这也很痛苦。