循環/反映所有EF模型中的所有屬性以設置列類型

asp.net-core entity-framework entity-framework-core

我的客戶端有一個存儲SQL Server小數的標準,帶有十進制(13,4)規範。因此,在一個非常龐大且仍在增長的架構中,我有近百個這樣的語句:

builder.Entity<MyObject>()
    .Property(x => x.MyField1)
    .ForSqlServerHasColumnType("decimal(13,4)");
builder.Entity<MyObject>()
    .Property(x => x.MyField2)
    .ForSqlServerHasColumnType("decimal(13,4)");
builder.Entity<MyObject2>()
    .Property(x => x.MyField1)
    .ForSqlServerHasColumnType("decimal(13,4)");

如果有一個功能我可以直接告訴EF所有小數都應該是十進制(13,4)默認情況下,我想使用它。如果沒有,我可以使用反射循環遍歷模型中的每個對象/屬性,所以我可以在幾個語句中執行此操作嗎?

就像是:

foreach(var efObj in EntityFrameWorkObjects)
{
    foreach (var objProperty in efObj)
    {
        if (objProperty is decimal || objProperty is decimal?)
        {
            builder.Entity<efObj>()
                .Property(x => x.efObj)
                .ForSqlServerHasColumnType("decimal(13,4)");
        }
    }
}

反射似乎是一個很好的方法,因為那時我可以實現一些其他約定,如果一個對像有一個名稱和描述,名稱是必需的,並限制為256個字符。

更新:我按照Ivan評論中的鏈接進行了調整,並對其進行了調整,這對我有用:

foreach (var p in builder.Model
    .GetEntityTypes()
    .SelectMany(t => t.GetProperties())
    .Where(p => 
        p.ClrType == typeof(decimal) ||
        p.ClrType == typeof(decimal?)))
{
    p.SqlServer().ColumnType = "decimal(13,4)";
}

不久之後,他提供了一個完整的答案,我稍微改變了以使用十進制和可以為零的小數:

foreach (var pb in builder.Model
    .GetEntityTypes()
    .SelectMany(t => t.GetProperties())
    .Where(p => 
        p.ClrType == typeof(decimal) ||
        p.ClrType == typeof(decimal?))
    .Select(p => 
        builder.Entity(p.DeclaringEntityType.ClrType)
            .Property(p.Name)))
{
    pb.ForSqlServerHasColumnType("decimal(13,4)");
}

兩種方法都有效!

更新2:我必須在上下文中將我的對象聲明為DbSet <>才能使上述工作正常。當我逐行設置屬性時,似乎不需要這樣做。

一般承認的答案

在EF Core v1.1.0中,您可以使用以下內容:

foreach (var pb in modelBuilder.Model
    .GetEntityTypes()
    .SelectMany(t => t.GetProperties())
    .Where(p => p.ClrType == typeof(decimal) || p.ClrType == typeof(decimal?))
    .Select(p => modelBuilder.Entity(p.DeclaringEntityType.ClrType).Property(p.Name)))
{
    pb.ForSqlServerHasColumnType("decimal(13,4)");
}

更新:從EF Core 2.0開始,模型是為每個數據庫提供程序單獨構建的,因此HasAbcXyz方法將替換為常見的HasXyz 。更新的代碼(也跳過顯式配置的屬性)如下所示:

foreach (var property in modelBuilder.Model.GetEntityTypes()
    .SelectMany(t => t.GetProperties())
    .Where(p => p.ClrType == typeof(decimal) || p.ClrType == typeof(decimal?)))
{
    if (property.Relational().ColumnType == null)
        property.Relational().ColumnType = "decimal(13,4)";
}


Related

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