前言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; }
但是,模型类是自动生成的,所以我认为更改它们是一个坏主意(如果刷新数据库模型,无论如何都会写入)。
我如何添加验证属性?
答案 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; }
}