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

私の期待は、マイグレーションを追加するとき(そしてその後のデータベースの更新)には、デフォルト値「My Default Description!」があるということです。ただし、 MyEntityDescription列の場合はそうではありません。

私はどんなエラーも出ませんが、それは私が疑うところでやっていませんし、ブレークポイントでOnModelCreatingを実行することも不可解に難しいです。

私はこれを正しくしていますか?それは単に機能しませんか? EF7ではサポートされていませんか?あるいは、私のPostgreSQL実装ではサポートされていませんか?どんな洞察にも感謝します。

更新 @ IvanStoevの答えを使用して、私はいくつかの軽微な修正(.NET CoreのReflectionは伝統とは少し異なります)で動作させることができました:

//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はあなたのカスタム属性については何も知らないので、それを発見してアノテーションとして公開する方法はありません(一般的には別のものであり、必ずしも属性に関連付けられているわけではありません)。

存在する場合、 PropertyInfoまたはFieldInfoから属性を手動で抽出する必要があります。

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は合法ですか? はい、理由を学ぶ