在EF7(核心)OnModelCreating中使用自定義屬性

c# ef-code-first entity-framework entity-framework-core npgsql

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

這就像一個冠軍。

一般承認的答案

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;
    }


Related

許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因
許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因