【问题标题】:Database First and View Models数据库优先和视图模型
【发布时间】:2016-10-12 10:03:09
【问题描述】:

我对数据库优先模型以及如何使用 MVC 视图模型处理这些模型的经验很少。

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

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

My DB First 生成的模型 - 请勿修改

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,即使我认为上面的设置器会处理这个(我在其余字段中使用 Automapper)所以我很困惑为什么这不起作用。

目前我正在控制器中进行验证,并且可能希望稍后对其进行重构以将它们移动到视图模型中,以便我可以使用 [Required] 注释以及 [Display (Name="Title")] 字段当前在视图中处理。

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

【问题讨论】:

  • 视图模型不继承数据模型。它是一个完全独立的模型,根本不了解数据模型。 What is ViewModel in MVC?
  • 是的,您可能犯的最大错误之一是将数据模型重用为视图模型。你进入了一个痛苦的世界!

标签: asp.net-mvc asp.net-mvc-4 ef-database-first


【解决方案1】:

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

模型和视图模型的区别

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

但是,视图模型不应该知道您的数据的结构。您只需分配其属性并将这些数据传递给视图。

考虑以下示例。您的数据库中有 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

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

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 将自动将已发布的表单与CustomerViewModel 类型的customer 绑定。现在我们只需要将存储在customer 中的数据传递到适当的数据模型中并保存到数据库中。

【讨论】:

  • 谢谢你,我可以理解为什么你应该将数据模型与视图模型分开,因此需要注释来实现解耦,但我想了解更多关于稍后如何绑定的信息在控制器中。目前,我的控制器看起来很流畅,但在您的示例中,我需要在控制器中做更多的手动映射,以使这项工作特别适用于创建和更新。
  • 我刚刚删除了我对 xmldata 的继承并复制了属性及其工作,谢谢。但是,我的 BlurbVm 属性仍然存在与允许 Html 相关的问题,我无法解决,删除此问题并将 [AllowHtml] 添加到 ViewModel 中的模糊似乎不起作用。
  • 您的问题到底是什么? HTML是编码的还是根本没有价值?很高兴我能帮上忙!
  • 好的,所以我删除了 BlurbVm 并在我的视图模型中将 [AllowHtml] 添加到公共字符串 blurb { get;放; } 虚拟机中的属性。这包含合法的 HTML,控制器落在“潜在危险的 Request.Form 值”上。在 UpdateModel(dbXmldata) dbXmldata 是 EntityContext 数据库记录。
【解决方案2】:

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

[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;}
}

另请参阅以下链接以进行说明:

Add data annotations to a class generated by entity framework

Data Annotations with Entity Framework 5.0 (database first)

【讨论】:

  • 使用 MVC 属性注释实体框架模型是一种不好的做法。
  • 微软建议这样做。创建新属性并分配也很糟糕。
  • 看,你没有抓住重点。首先,OP 不应该从实体模型继承视图模型。完全使用单独的视图模型。其次,您不应该在实体类上使用特定于 MVC 的属性。第三,您不仅继承自xmldata,而且包含该类型的属性,因此您的XmlDataViewModel既是-a又是-a xmldata,这没有任何意义.所以这个答案完全展示了不好的建议(使用实体模型作为视图模型的 MVC 教程同样传播了不好的建议)。
  • 对不起..我忘了从视图模型中删除继承的类,现在我删除了..但我不接受第二点。 B 因为我没有向自动生成的类文件添加属性。请给我解决方案,我会感谢你。
猜你喜欢
  • 2012-08-12
  • 2013-03-13
  • 2015-08-11
  • 2011-07-23
  • 2023-04-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多