【问题标题】:Adding Validation Attributes With an Entity Framework Data Model使用实体框架数据模型添加验证属性
【发布时间】:2012-12-13 03:00:28
【问题描述】:

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

Getting Started with Entity Framework 6 Code First using MVC 5

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

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

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

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

如何添加验证属性?

【问题讨论】:

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


【解决方案1】:

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

【讨论】:

  • 其实你不应该尝试修改原始自动生成的文件,只需创建另一个文件,因为 partial 关键字将使其像魅力一样工作。
  • 编译器会产生警告说 ContactName “从未分配给,并且将始终具有其默认值 null”;像这样的默认属性是否安全?
  • 它给了我“这个成员被定义了不止一次” :(
  • 我注意到一旦你有一个 EF 模型的元数据类,例如要添加额外的验证,您似乎会丢失 EF 模型已经提供的任何现有验证。元数据作为属性的替代品而不是扩展现有的属性集是否正确?
  • @SteveCav 我也遇到了这个错误。您现在可能已经弄明白了,但如果还没有,则需要将元数据类与具有相同命名空间的模型类放在同一个程序集中。
【解决方案2】:

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 - 顺便说一句,无需警告。

【讨论】:

    【解决方案3】:

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

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

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

    【讨论】:

      【解决方案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;
      }
      

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

      【讨论】:

        【解决方案5】:

        此处建议的答案有一个变体,允许您在不同的程序集和命名空间中使用类。我还没有用 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; }
        }
        

        【讨论】:

          猜你喜欢
          • 2018-10-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-03-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多