数据库优先和视图模型

Database First and View Models

我对数据库优先模型以及如何使用 MVC 视图模型处理这些模型没有什么经验。

很明显我无法更改原始模型,但我想为模型添加一些注释以进行验证。

因此我尝试做的是创建一个继承自实体的 ViewModel

我的DB先生成模型-请勿修改

public partial class xmldata
{
    public string ISBN { get; set; }
    public string title { get; set; }
    public string blurb { get; set; }
    ...
}

然后我创建了一个视图模型,如下所示,它继承自 xmldata

public class XmlDataViewModel : xmldata
{
    [AllowHtml]
    [Display(Name = "Blurb")]
    public string BlurbVm {
        get { return blurb; }
        set { blurb = value; }
    }
    ...
}

上面显示的字段我需要 AllowHtml 和我目前最好的解决方案,但是在控制器操作中我仍然必须手动将 BlurbVm 字段映射回 blurb,即使我认为 setter上面会处理那个(我在其余字段中使用 Automapper)所以我很困惑为什么这不起作用。

目前我正在控制器中进行验证,稍后可能想重构它以将它们移动到视图模型中,这样我就可以使用 [Required] 注释和 [Display (Name="Title")] 当前在视图中处理的字段。

可能我的总体问题是,在使用数据库优先模型时,我是否使用了处理模型注释和视图模型的最佳策略。

您可以向主域模型添加数据注释。创建手动数据注释时确保命名空间与生成的 class 的命名空间相同。

[MetadataType(typeof(XmlDataDataAnnotation))]
public partial class xmldata{ }

public class XmlDataDataAnnotation
{
  [AllowHtml]
  [Display(Name = "Blurb")]
  public string blurb { get; set; }
}

然后您可以在您的视图模型中创建复杂的 属性。

public class XmlDataViewModel
{
  public xmldata XmlData {get;set;}
}

另请参阅下文link进行说明:

Add data annotations to a class generated by entity framework

Data Annotations with Entity Framework 5.0 (database first)

我想我可能会添加一些关于为什么数据模型不同于视图模型的详细解释

模型和视图模型的区别

正如@Stephen Muecke 在评论中提到的那样,您正在混合两种不同的东西。视图模型有一个目的——从控制器获取数据并将其传输到视图。在复杂的情况下,您想要向用户展示的数据与您的数据库看起来完全不同。要在您的代码中表示您的数据结构,您可以使用数据模型。它具有与您在数据库中完全相同的属性。

但是视图模型不应该知道您的数据是如何构建的。您只需简单地分配其属性并将这些数据传递给视图。

考虑以下示例。您的数据库中有 CustomersOrders 个表。

客户:

ID | Firstname | Lastname

订单:

ID | Amount | CustomerID

为了在您的代码中映射这些数据,您必须创建两个 类

public class Customer
{
    public int ID { get; set; }
    public string Firstname { get; set; }
    public string Lastname { get; set; }
}

public class Order
{
    public int ID { get; set; }
    public decimal Amount { get; set; }
    public int CustomerID { get; set; }
}

但是在您的应用程序中您有一些视图,您希望在其中显示客户的名字和他们在您的商店中花费的总金额。您可以创建视图模型,它正是用于此目的。

public CustomersViewModel
{
    public string Firstname { get; set; }
    public decimal TotalAmount { get; set; }
}

看看这个视图模型与您的数据模型相比有何不同?它不知道 ID 值,也不知道 Lastname

此模型仅用于正确显示您的数据,因此您可以在此处使用您想要的所有 DataAnnotation

public CustomersViewModel
{
    public string Firstname { get; set; }

    [DisplayFormat(DataFormatString="{0:#.####}")]
    public decimal TotalAmount { get; set; }
}

为什么他们在 MSDN 上注释数据模型?

因为就像@CodeCaster 提到的那样——这是不好的做法,但并不被禁止。如果您的应用程序非常简单,您可以完全跳过视图模型!这是个坏主意吗?是的 - 即使在简单的情况下,您也应该使用专用的视图模型,因为它不会花费您任何费用,但可以将您的视图与数据结构分离。我猜他们不想使这些示例复杂化,因此在阅读本教程时,您应该只关注 如何 使用 DataAnnotations.

如何在控制器中绑定自定义视图模型?

视图模型的使用不限于将它们返回到视图以简单地显示一些数据。如果你想传递数据供用户修改,你可以使用它们。拥有与数据模型具有完全相同属性的视图模型是绝对可以接受的。考虑到前面的示例,我们可以在 EditCustomer.cshtml 视图中使用 CustomerViewModel

在这个视图中,我们的编辑表单看起来像这样

@model CustomerViewModel

// HTML markup
@Html.LabelFor(m => m.Firstname)
@Html.TextboxFor(m => m.Firstname)
// another properties similar

如果我们在 CustomerController 中的 Edit 方法看起来像这样

public Edit(CustomerViewModel customer)

我们没有太多要做的了。 ASP.NET 将自动绑定类型为 CustomerViewModelcustomer 发布的表单。现在我们只需要将存储在 customer 中的数据传递到适当的数据模型中并将其保存在数据库中。