【问题标题】:Using a custom attribute in EF7 (core) OnModelCreating在 EF7(核心)OnModelCreating 中使用自定义属性
【发布时间】:2017-05-30 14:27:24
【问题描述】:

我有一个 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; }
}

我用这个属性装饰了我的几个实体,如下所示:

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

然后,在我的数据库上下文中的 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;
        }
    }

我的期望是,在添加迁移(以及后续的数据库更新)时,会有一个默认值“我的默认描述!”对于MyEntityDescription 列...但是,情况并非如此。

我没有收到任何错误,但它并没有像我想象的那样做,并且使用断点进入 OnModelCreating 也莫名其妙地难以做到。

我这样做正确吗?它只是不起作用吗? EF7 不支持它吗?还是我的 PostgreSQL 实现不支持它?任何见解将不胜感激。

更新 使用@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;
    }

这就像一个冠军。

【问题讨论】:

    标签: c# entity-framework ef-code-first entity-framework-core npgsql


    【解决方案1】:

    EF Core 对您的自定义属性一无所知,因此无法发现它并将其作为注释公开(通常是不同的东西,不一定与属性相关联)。

    您必须手动从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;
        }
    

    【讨论】:

    猜你喜欢
    • 2017-05-25
    • 2017-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-04
    • 1970-01-01
    • 2020-07-21
    • 2010-11-22
    相关资源
    最近更新 更多