向实体框架生成的类添加数据注释

本文关键字:添加 数据 注释 实体 框架 | 更新日期: 2023-09-27 18:15:06

我有以下由实体框架生成的类:

public partial class ItemRequest
{
    public int RequestId { get; set; }
    //...

我想将此设置为必填字段

[Required]
public int RequestId { get;set; }

但是,因为这是生成的代码,所以它将被清除。我无法想象创建分部类的方法,因为属性是由生成的分部类定义的。如何以安全的方式定义约束?

向实体框架生成的类添加数据注释

生成的类ItemRequest将始终是partial类。这允许您编写用必要的数据注释标记的第二个部分类。在您的例子中,部分类ItemRequest看起来像这样:

using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
//make sure the namespace is equal to the other partial class ItemRequest
namespace MvcApplication1.Models 
{
    [MetadataType(typeof(ItemRequestMetaData))]
    public partial class ItemRequest
    {
    }
    public class ItemRequestMetaData
    {
        [Required]
        public int RequestId {get;set;}
        //...
    }
}

正如MUG4N回答的那样,您可以使用部分类,但最好使用接口。在这种情况下,如果EF模型与验证模型不对应,就会出现编译错误。因此,您可以修改您的EF模型,而不必担心验证规则已经过时。

using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace YourApplication.Models
{
    public interface IEntityMetadata
    {
        [Required]
        Int32 Id { get; set; }
    }
    [MetadataType(typeof(IEntityMetadata))]
    public partial class Entity : IEntityMetadata
    {
        /* Id property has already existed in the mapped class */
    }
}

注:如果您使用的项目类型不同于ASP。. NET MVC(当你执行手动数据验证时)不要忘记注册你的验证器

/* Global.asax or similar */
TypeDescriptor.AddProviderTransparent(
    new AssociatedMetadataTypeTypeDescriptionProvider(typeof(Entity), typeof(IEntityMetadata)), typeof(Entity));

我找到了一个类似于MUG4N的答案的解决方案,但相反,将MetaData类嵌套在实体类中,从而减少了公共名称空间列表中的类数量,并且消除了为每个元数据类具有唯一名称的需要。

using System.ComponentModel.DataAnnotations;
namespace MvcApplication1.Models 
{
    [MetadataType(typeof(MetaData))]
    public partial class ItemRequest
    {
        public class MetaData
        {
            [Required]
            public int RequestId;
            //...
        }
    }
}

这是@dimonser答案的一种扩展,如果您重新生成数据库模型,您将不得不手动重新添加这些类的接口。

如果你有胃,你也可以修改你的.tt模板:

这是一些类上自动生成接口的例子,这是.tt的片段,只是用以下方法替换EntityClassOpening方法(显然var stringsToMatch与您的实体名称和接口)。

public string EntityClassOpening(EntityType entity)
{
    var stringsToMatch = new Dictionary<string,string> { { "Answer", "IJourneyAnswer" }, { "Fee", "ILegalFee" } };
    return string.Format(
        CultureInfo.InvariantCulture,
        "{0} {1}partial class {2}{3}{4}",
        Accessibility.ForType(entity),
        _code.SpaceAfter(_code.AbstractOption(entity)),
        _code.Escape(entity),
        _code.StringBefore(" : ", _typeMapper.GetTypeName(entity.BaseType)),
        stringsToMatch.Any(o => _code.Escape(entity).Contains(o.Key)) ? " : " + stringsToMatch.Single(o => _code.Escape(entity).Contains(o.Key)).Value : string.Empty);
}

正常人不应该这样对自己,圣经中已经证明,一个人会因此而下地狱。

我不知道如何做你所要求的,但有一种方法。通过覆盖自定义DataAnnotationsModelValidatorProvider的GetValidators来进行动态数据验证。在其中,您可以读取用于验证每个字段的规则(来自数据库、配置文件等),并根据需要添加验证器。它的附加价值是,您的验证不再与模型紧密耦合,甚至不需要重新启动站点就可以进行更改。当然,这对你的案子来说可能有点过分,但对我们的案子来说是理想的!

修改T4模板,添加所需的注释,该文件通常命名为MODELNAME.tt

查找T4在哪里创建类和方法,以知道将它们放在哪里。

     <#=codeStringGenerator.IgnoreJson(navigationProperty)#>

//create this method in file
public string IgnoreJson(NavigationProperty navigationProperty){
            string result = navigationProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many ? "" : @"[JsonIgnore]
    [IgnoreDataMember]";
            return result;
        }

您还需要添加名称空间;

<#=codeStringGenerator.UsingDirectives(inHeader: false)#>
using System.ComponentModel.DataAnnotations;
using Newtonsoft.Json;
using System.Runtime.Serialization;

通过保存你的模型来重建你的类,你所有的方法都应该被注释。