24

2015 年 2 月前言如果您仍在使用实体框架 EDMX,请帮自己一个忙,并使用实体框架代码优先结帐。不同之处在于您的表是从您的模型类创建的,而不是在 EDMX 中,您的模型类是使用您的表创建的。这是一个更简单的解决方案,而且这个问题中的问题甚至不存在!

使用 MVC 5 开始使用 Entity Framework 6 Code First

我有一个现有的 SQL 数据库,并且我正在为模型使用 ADO.NET 实体数据模型。我正在尝试在我的 MVC 应用程序中构建一些 CRUD 功能。

在我找到的有关该主题的所有教程中,他们从头开始构建模型并将属性添加到模型类中。例如:

    [Required]
    [StringLength(10)]
    public string Name { get; set; }

但是,模型类是自动生成的,所以我认为更改它们是一个坏主意(如果刷新数据库模型,无论如何都会被覆盖)。

我将如何添加验证属性?

4

5 回答 5

36

您可以创建一个与 EF 生成的类分开的部分类来存储元数据。

//Contact.cs - The original auto-generated file 
[System.ComponentModel.DataAnnotations.MetadataType(typeof(ContactMetadata))]
public partial class Contact
{
    public int ContactID { get; set; }
    public string ContactName { get; set; }
    public string ContactCell { get; set; }
}

//ContactMetadata.cs - New, seperate class

using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
internal sealed class ContactMetadata
{
    [Required(ErrorMessage = "Name is required.")]
    [StringLength(5)]  
    public string ContactName;
}
于 2012-12-27T19:03:46.233 回答
19

Mason240 答案效果很好,我会尝试改进它:您可以创建一个新的 ContactDataAnnotations.cs 类:

//ContactDataAnnotations.cs - A new file 
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;

[MetadataType(typeof(ContactMetadata))]
public partial class Contact
{
    // No field here
}

internal sealed class ContactMetadata
{
    [Required(ErrorMessage = "Name is required.")]
    [StringLength(5)]  
    public string ContactName {get; set; }
}

这样,您可以通过 EF 重新生成您的 Contact 类,而无需触及 DataAnnotations - 顺便说一下,无需警告。

于 2014-04-25T10:46:30.667 回答
4

这已经得到了正确的回答,但我还想补充一点,我总是发现嵌套元数据对我来说似乎更干净一些,恕我直言。

[MetadataType(typeof(ProductDescription.Metadata))]
public partial class ProductDescription
{
    sealed class Metadata
    {
        [Key]
        public long id { get; set; }
        [Display(Name = "Title")]
        public string title { get; set; }
        // ...
    }
}

我还注意到将元数据保持为类私有的一个额外好处。该属性仅适用于正确的类,防止在复制该类时可能发生的错误(以创建类似的类)。如果您在重命名重复的类时忘记更改属性中的类名,则会出现该错误。

于 2015-04-01T01:25:09.903 回答
4

我知道这已被标记为已回答,但我想清理一些东西。

@SteveCav 说:“这个成员被定义了不止一次”。我有同样的错误。花了几个小时试图弄清楚。

要最终纠正它,您必须在同一个程序集中创建一个单独的文件类(我认为这已经在这里提到过)。但我要强调的是,这个类应该嵌套在一个代表内部类的部分类中。

然后你用 Annotation 类装饰那个内部类。像这样:

//ContactMap.cs - Present in the same namespace as Contact.cs
[System.ComponentModel.DataAnnotations.MetadataType(typeof(ContactMap))]
partial class Contact // Present in the ContactMap class. This represent the Inner Class
{
}

//ContactMap.cs - This represent the outer class

using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
public class ContactMetadata
{
    [Required(ErrorMessage = "Name is required.")]
    [StringLength(5)]  
    public string ContactName;
}

希望这更清楚或更容易理解。

于 2015-04-22T13:08:53.557 回答
3

这里建议的答案有一个变体,允许您在不同的程序集和命名空间中使用类。我实际上没有用 EF 测试过它,但我将它用于 Swagger 代码生成 API 模型类。

简而言之:从模型类继承并在继承的类上添加元数据。另一个好处是,使用 Swagger 代码生成,您可以直接使用 API 模型而无需映射,并且对于初始表单,您可以使用受保护的默认 ctor。

[MetadataType(typeof(LocalAssemblyModelMetadata))]
public class LocalAssemblyModel : IO.Swagger.Model.OtherAssemblyModel 
{
    public LocalAssemblyModel() : base ()     { }
}



public sealed class LocalAssemblyModelMetadata
{
    [Required(ErrorMessage = "BaseclassProperty is mandatory.")]
    public string BaseclassProperty { get; set; }
}
于 2016-10-05T08:36:21.833 回答