我想动态创建我的数据模型以使用一些现有的类和自定义XML映射文件,因为我有很多现有的表和许多现有的业务类(可能很疯狂,我不知道)。
对于使用不同列名的属性或者与我想要调用的现有列不对应的属性.Ignore()和.HasColumnName()但是我想用它来做。
所以我希望能够像这样进行调用,但我想基于反射和使用Linq.Expressions的XML配置文件动态制作它们(我从来没有使用过它):
modelBuilder.Entity<Product>().Property(p => p.QuantityInStock).HasColumnName("UnitsInStock");
或
modelBuilder.Entity<Product>().Ignore(p => p.QuantityInStock);
这就是我正在尝试的(最终我会引用我的XML地图来确定要映射的属性和要忽略的属性):
Type entityType = typeof(Product);
var config = modelBuilder.GetType().GetMethod("Entity")
.MakeGenericMethod(entityType)
.Invoke(modelBuilder, null);
var ignore = config.GetType().GetMethod("Ignore").MakeGenericMethod(entityType);
var paramEx = Expression.Parameter(entityType);
var lambdaEx = Expression.Lambda(Expression.Property(paramEx, "QuantityInStock"), paramEx);
ignore.Invoke(config, new[] { lambdaEx });
但是我的lambda表达不对:
Object of type 'System.Linq.Expressions.Expression`1[System.Func`2[ConsoleApplication2.Product,System.Int16]]'
cannot be converted to type
'System.Linq.Expressions.Expression`1[System.Func`2[ConsoleApplication2.Product,ConsoleApplication2.Product]]'.
答案 0 :(得分:1)
Ignore
方法的泛型类型参数是错误的。将您的代码更改为:
var paramEx = Expression.Parameter(entityType);
var prop = Expression.Property(paramEx, "QuantityInStock");
var lambdaEx = Expression.Lambda(prop, paramEx);
var ignore = config.GetType().GetMethod("Ignore").MakeGenericMethod(prop.Type);
编辑:致电HasColumnName
:
var property = config.GetType().GetMethod("Property", new Type[] { lambdaEx.GetType() });
var hasColumnName = property.ReturnType.GetMethod("HasColumnName");
hasColumnName.Invoke(
property.Invoke(config, new[] { lambdaEx }),
new[] { "UnitsInStock" });
但是,这对于从long
或类似的重载列表中排除的结构不起作用,property
的值在这些情况下为null
。因此,您必须使用Property
搜索通用GetMethods
方法并选择适当的方法(Nullable<T>
参数中包含或不包含Expression
类型。
答案 1 :(得分:0)
IMO这不是Fluent API的预期目的。 Fluent API的全部目的是提供更易读,更简单的配置方式,同时为您提供编译时的安全性。我没有看到这种方法。
外部化配置的更好方法是使用EntityTypeConfiguration
类并将其添加到ModelBuilder
。