简体   繁体   English

在EF7(核心)OnModelCreating中使用自定义属性

[英]Using a custom attribute in EF7 (core) OnModelCreating

I have a DefaultAttribute defined like so: 我有一个DefaultAttribute定义如下:

[AttributeUsage(AttributeTargets.Property)]
public class DefaultAttribute : Attribute
{
    /// <summary>
    /// Specifies this property has a default value upon creation.
    /// </summary>
    /// <param name="defaultValue">The default value of the property.</param>
    /// <param name="useAsLiteral">Set to true if the value is <em>not</em> quoted in the DDL.</param>
    public DefaultAttribute(object defaultValue, bool useAsLiteral = false)
    {
        DefaultValue = defaultValue;
        UseAsLiteral = useAsLiteral;
    }

    public object DefaultValue { get; private set; }

    /// <summary>
    /// True if the default value is not quoted in the DDL
    /// </summary>
    public bool UseAsLiteral { get; private set; }
}

I have decorated several of my entities with this attribute, like so: 我用这个属性装饰了我的几个实体,如下所示:

public class MyEntity
{
    . . . (other properties) . . .
    [StringLength(200)]
    [Required]
    [Default("My Default Description!")]
    public string Description { get; set; }
}

Then, in my OnModelCreating method in my database context, I wrote the following code: 然后,在我的数据库上下文中的OnModelCreating方法中,我编写了以下代码:

//examine custom annotations for shaping the schema in the database.
foreach (var entityType in builder.Model.GetEntityTypes())
    foreach (var property in entityType.GetProperties())
    {
        var annotations = property.GetAnnotations();

        // evaluate default values
        var defaultAnnotation = annotations.FirstOrDefault(x => x.Name == typeof(DefaultAttribute).FullName);
        if (defaultAnnotation != null)
        {
            var defaultValue = defaultAnnotation.Value as DefaultAttribute;
            if (defaultValue == null) continue;

            if (defaultValue.UseAsLiteral)
                property.Npgsql().DefaultValueSql = defaultValue.DefaultValue.ToString();
            else
                property.Npgsql().DefaultValue = defaultValue.DefaultValue;
        }
    }

My expectation, when adding a migration, (and subsequent database update) is that there would be a default value of "My Default Description!" 在添加迁移(以及后续数据库更新)时,我的期望是默认值为“我的默认描述!”。 for the Description column of MyEntity ... however, that is not the case. 对于MyEntityDescription列...但是,情况并非如此。

I'm not getting any errors, but it's not doing as I would suspect, and stepping into OnModelCreating with a breakpoint is also inexplicably difficult to do. 我没有得到任何错误,但它没有像我怀疑的那样做,并且使用断点进入OnModelCreating也难以理解。

Am I doing this correctly? 我这样做了吗? Does it just not work? 它不起作用吗? Is it just not supported in EF7? 它只是不支持EF7吗? Or is it not supported in my PostgreSQL implementation? 或者我的PostgreSQL实现不支持它? Any insight would be appreciated. 任何见解将不胜感激。

UPDATE Using @IvanStoev's answer, I was able to get this to work with some minor modifiactions (Reflection in .NET Core a bit different from traditional): 更新使用@ IvanStoev的答案,我能够使用一些小的修改(.NET Core中的反射与传统的有点不同):

//examine custom annotations for shaping the schema in the database.
foreach (var entityType in builder.Model.GetEntityTypes())
    foreach (var property in entityType.GetProperties())
    {
        var memberInfo = property.PropertyInfo ?? (MemberInfo)property.FieldInfo;
        var defaultValue = memberInfo?.GetCustomAttribute<DefaultAttribute>();
        if (defaultValue == null) continue;
        if (defaultValue.UseAsLiteral)
            property.Npgsql().DefaultValueSql = defaultValue.DefaultValue.ToString();
        else
            property.Npgsql().DefaultValue = defaultValue.DefaultValue;
    }

This worked like a champ. 这就像一个冠军。

EF Core knows nothing about your custom attribute, so there is no way it to be discovered and exposed as annotation (which in general is a different thing and not necessarily associated with attribute). EF Core对您的自定义属性一无所知,因此无法将其作为注释进行发现和公开(通常是一个不同的东西,不一定与属性相关联)。

You have to extract the attribute manually from PropertyInfo or FieldInfo when present: 您必须在存在时从PropertyInfoFieldInfo手动提取属性:

foreach (var entityType in builder.Model.GetEntityTypes())
    foreach (var property in entityType.GetProperties())
    {
        var memberInfo = property.PropertyInfo ?? (MemberInfo)property.FieldInfo;
        if (memberInfo == null) continue;
        var defaultValue = Attribute.GetCustomAttribute(memberInfo, typeof(DefaultAttribute)) as DefaultAttribute;
        if (defaultValue == null) continue;
        if (defaultValue.UseAsLiteral)
            property.Npgsql().DefaultValueSql = defaultValue.DefaultValue.ToString();
        else
            property.Npgsql().DefaultValue = defaultValue.DefaultValue;
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM