使用实体框架数据模型添加验证属性

时间:2012-12-27 18:31:52

标签: entity-framework asp.net-mvc-4

前言2015年2月如果您仍在使用Entity Framework EDMX,请使用Entity Framework Code First代替您自己帮忙和结帐。不同之处在于您的表是从模型类创建的,而不是在使用表创建模型类的EDMX中创建的。这是一个全面的解决方案,这个问题中的问题甚至不存在!

Getting Started with Entity Framework 6 Code First using MVC 5

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

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

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

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

我如何添加验证属性?

5 个答案:

答案 0 :(得分:35)

您可以创建一个与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;
}

答案 1 :(得分:18)

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 - 顺便说一下,没有任何警告。

答案 2 :(得分: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; }
        // ...
    }
}

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

答案 3 :(得分: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;
}

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

答案 4 :(得分:3)

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

简而言之:从模型类继承并在继承的类上添加元数据。另外一个好处是,使用Swagger codegen,您可以直接使用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; }
}