循环/反映所有 EF 模型中的所有属性以设置列类型 [英] Loop/reflect through all properties in all EF Models to set Column Type
问题描述
我的客户有一个存储 SQL Server 小数的标准,其中包含小数 (13,4) 规范.结果,在一个非常大且仍在增长的模式中,我有近一百个这样的语句:
My client has a standard of storing SQL Server decimals with a decimal(13,4) specification. As a result, in a very large and still-growing schema, I have nearly a hundred statements like these:
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),我想使用它.如果没有,我是否可以使用反射来遍历模型中的每个对象/属性,以便我可以在几个语句中执行此操作?
If there is a feature where I can tell EF directly that all decimals should be decimal(13,4) by default, I would like to use that. If not, can I use reflection to loop through every object/property in the model so I can do this in a couple statements?
类似于:
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 个字符.
Reflection seems like a great way to go, because then I can implement some of our other conventions where, if an object has a Name and Description, the Name is required and limited to 256 chars.
更新:我按照伊万评论中的链接进行了修改,这对我有用:
Update: I followed the link in Ivan's comment and adapted it to this, which works for me:
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)";
}
不久之后,他提供了一个完整的答案,我稍微修改了一下以使用十进制和可为空的十进制:
Soon after, he provided a full answer, which I changed slightly to work with both decimal and 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<> 才能使上述内容正常工作.当我逐行设置属性时,这似乎不是必需的.
Update 2: I had to have my objects declared as DbSet<> in the context for the above to work. This didn't seem to be required when I was setting properties line by line.
推荐答案
在 EF Core v1.1.0 中,您可以使用以下内容:
In EF Core v1.1.0 you can use something like this:
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.更新后的代码(也跳过了显式配置的属性)如下所示:
Update (EF Core 2.x): Starting from EF Core 2.0, the model is built separately for each database provider, so HasAbcXyz
methods are replaced with common HasXyz
. The updated code (which also skips the explicitly configured properties) looks like this:
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
方法对),代码如下:
Update (EF Core 3.x): With EF Core 3.0 metadata API changes (Relational()
extensions removed, properties replaced with Get
/ Set
method pair), the code is as follows:
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)");
}
这篇关于循环/反映所有 EF 模型中的所有属性以设置列类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!