0

我想动态创建我的数据模型来处理一些现有的类和一个自定义 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]]'.
4

2 回答 2

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方法(在参数中有或没有类型)。GetMethodsNullable<T>Expression

于 2012-03-19T16:38:43.657 回答
0

IMO 这不是 Fluent API 的预期目的。Fluent API 的全部目的是提供更具可读性和更简单的配置方式,同时为您提供编译时安全性。我看不到这种方法。

将配置外部化的更好方法是使用EntityTypeConfiguration类并将这些添加到ModelBuilder.

于 2012-03-19T15:49:21.733 回答