2

我正在使用 EF-CodeFirst 从我的 Poco 对象及其配置创建数据库。我大量使用 Dataannotation (Required、DataLength、RegularExpression、DataType) 来获取 MVC 的元数据,并让错误消息指向资源以便稍后本地化它们。

对于简单的 CRUD 操作,这不是问题。

但是一旦我需要 ViewModel 类,我就会从我的 Poco 对象中释放 Dataannotations。

如何在不损害 DRY(不要重复自己)原则的情况下将这两种设计结合起来?

谢谢安德烈亚斯

4

2 回答 2

4

这两种设计不能也不应该结合起来。您的视图模型与视图相关联,因此我个人重新定义了视图模型上的所有必要属性,无论您信不信,在这种情况下我并不关心 DRY。我这样做是因为我的视图要求经常变化(是的,客户是反复无常的),而我总是重用相同的域模型。对我来说,视图永远不应该知道域模型的存在。视图应该是虚拟的,它应该知道的只是控制器传递给它的视图模型。

我知道有些人可能会有不同的想法,我尊重他们的意见。因此,通过这样说,我只是暴露了我的个人观点和我使用 ASP.NET MVC 的方式。老实说,我的模型是没有任何 DataAnnotations 的 POCO 对象,所以我不会遇到此类问题。我在我的视图模型上使用 DataAnnotations 仅用于格式化目的(诸如 和 之类的东西)DataType并且没有验证属性。为此,我使用FluentValidation.NETDisplayNameDisplayFormat

于 2011-02-13T20:00:13.177 回答
2

你可以很容易地完成你所要求的。Darin 有一个非常有效的观点,适用于较大的项目,但我认为对于较小的项目,这听起来有点矫枉过正。似乎这在很大程度上取决于您是使用 DataAnnotations 进行验证还是使用 3rd 方库。恕我直言,不这样做所涉及的重复将造成相当大的维护麻烦。还有一个事实是您花费大量代码行只是将数据从数据库复制到视图模型;ORM 应该有助于消除这种情况,但到目前为止,解决方案似乎并不是很好。

这是一个关于如何做你想做的事的示例代码片段。第一个类是部分的,主体在 EF 生成的代码中(我先是模型,而不是代码)。此外,作为示例,Question 对 QuestionGroup 有一个 FK。在数据库中,这是一个名为 GroupID 的列,但在 ViewModel 中有一个名为 GroupName 的属性,用于在一个漂亮的小网格中显示(实际上,Telerik 网格,如果你尝试传入一个 EF 对象,它基本上会中断)。

[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,这也很痛苦。

于 2011-05-04T13:00:10.313 回答