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

我的期望是,在添加遷移時(和隨後的數據庫更新),會有一個默認值「我的默認描述!」對於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對您的自定義屬性一無所知,因此無法將其作爲註釋來發現和公開(它通常是不同的事物,不一定與屬性相關聯)。

你必須從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; 
    } 
+0

注意,有沒有真正的理由這樣做'.Npgsql()' - 這對只爲Npgsql的設置默認值,當針對多個數據庫。在大多數情況下,您應該簡單地執行'property.HasDefaultValue(...)'(請參閱https://docs.microsoft.com/en-us/ef/core/modeling/relational/default-values) –