3

У меня есть DefaultAttribute определяется следующим образом:Использование пользовательского атрибута в EF7 (ядра) OnModelCreating

[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!» для столбца DescriptionMyEntity ... однако, это не так.

Я не получаю никаких ошибок, но это не так, как я подозревал, и переход на OnModelCreating с точкой останова также необъяснимо сложно.

Я делаю это правильно? Это просто не работает? Это просто не поддерживается в EF7? Или это не поддерживается в моей реализации PostgreSQL? Любое понимание было бы оценено.

UPDATE Использование @ ответ IvanStoev, я был в состоянии получить эту работу с некоторыми незначительными modifiactions (Отражение в .NET Ядра немного отличается от традиционного):

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

Это работает как чавканье ,

ответ

6

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

Обратите внимание, что нет никакой реальной причины, чтобы сделать '.Npgsql()' - это для установки значения по умолчанию только для Npgsql, когда нацеливание на несколько баз данных. В большинстве случаев вам просто нужно выполнить 'property.HasDefaultValue (...)' (см. Https://docs.microsoft.com/en-us/ef/core/modeling/relational/default-values) –