Verwenden eines benutzerdefinierten Attributs in EF7 (Core) OnModelCreating

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

Frage

Ich habe ein DefaultAttribute wie DefaultAttribute definiert:

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

Ich habe mehrere meiner Entitäten mit diesem Attribut dekoriert, so:

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

Dann schrieb ich in meiner OnModelCreating-Methode in meinem Datenbankkontext den folgenden Code:

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

Ich erwarte beim Hinzufügen einer Migration (und der anschließenden Datenbankaktualisierung), dass ein Standardwert von "Meine Standardbeschreibung" vorhanden wäre. für die Description Spalte von MyEntity ... das ist jedoch nicht der Fall.

Ich bekomme keine Fehler, aber es geht nicht so, wie ich es vermuten würde, und es ist auch unerklärlicherweise schwer, OnModelCreating mit einem Breakpoint zu OnModelCreating .

Mache ich das richtig? Funktioniert es einfach nicht? Wird es in EF7 nicht unterstützt? Oder wird es in meiner PostgreSQL-Implementierung nicht unterstützt? Jeder Einblick würde geschätzt werden.

UPDATE @ IvanStoev Antwort konnte ich dies mit einigen kleineren modifiactions (Reflection in .NET Kern ein wenig unterscheidet sich von traditionellen) zur Arbeit kommen:

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

Das hat wie ein Champion funktioniert.

Akzeptierte Antwort

EF Core weiß nichts über Ihr benutzerdefiniertes Attribut, daher gibt es keine Möglichkeit, es als Annotation zu entdecken und verfügbar zu machen (was im Allgemeinen eine andere Sache ist und nicht unbedingt mit dem Attribut verbunden ist).

Sie müssen das Attribut manuell aus PropertyInfo oder FieldInfo wenn es vorhanden ist:

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

Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum
Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum