我的客户有一个存储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.x):从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)";
}
更新(EF Core 3.x):更改了EF Core 3.0元数据API(删除了
Relational()
扩展名,将属性替换为Get
/Set
方法对),代码如下:foreach (var property in modelBuilder.Model.GetEntityTypes()
.SelectMany(t => t.GetProperties())
.Where(p => p.ClrType == typeof(decimal) || p.ClrType == typeof(decimal?)))
{
if (property.GetColumnType() == null)
property.SetColumnType("decimal(13,4)");
}
关于entity-framework - 循环/遍历所有EF模型中的所有属性以设置列类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45463349/