代码之家  ›  专栏  ›  技术社区  ›  Brondahl

(在efcore中)如何根据常规类型规则配置基础数据库列类型[重复]

  •  0
  • Brondahl  · 技术社区  · 6 年前

    我的客户机有一个存储带有decimal(13,4)规范的sql server小数的标准。因此,在一个非常大且仍在增长的模式中,我有将近100个这样的语句:

    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个字符。

    更新: 我遵循了伊凡评论中的链接,并将其改编为适合我的:

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

    不久之后,他给出了一个完整的答案,我稍微修改了一下,同时使用了decimal和nullable decimal:

    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<>,才能工作。当我逐行设置属性时,这似乎不是必需的。

    0 回复  |  直到 8 年前
        1
  •  29
  •   Ivan Stoev    6 年前

    在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)";
    }