我的客户端有一个标准,用于存储带有十进制(13,4)规范的SQL Server小数。因此,在一个非常庞大且仍在增长的架构中,我有近百个这样的陈述:
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)";
}
不久之后,他提供了一个完整的答案,我稍微改了一下,以使用十进制和可空的十进制:
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&lt;&gt;在上下文工作的上下文中。当我逐行设置属性时,似乎不需要这样做。
答案 0 :(得分:26)
在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)";
}
答案 1 :(得分:1)
当我使用 EFCore 5.0.1 DB-First 时,上述方法不起作用。 MS document 上的以下方法有效:
[Column(TypeName = "decimal(18, 4)")]
public decimal Numeric { get; set; }
答案 2 :(得分:0)
新功能将在EF Core 5.0中引入
modelBuilder
.Entity<Blog>()
.Property(b => b.Numeric)
.HasPrecision(16, 4);
参考:https://docs.microsoft.com/en-us/ef/core/what-is-new/ef-core-5.0/whatsnew#preview-4