2012-03-19 46 views
0

我想动态地创建我的数据模型来处理一些现有的类和一个自定义的XML映射文件,因为我有很多现有的表和大量现有的业务类(也许疯狂,不知道)。EF4.1的动态流利映射

对于使用不同列名称或与现有列不相对应的属性,我想调用.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]]'. 

回答

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在结构工作这些情况。因此,您必须使用GetMethods搜索通用的Property方法,并选择合适的方法(Expression参数中有或没有Nullable<T>类型)。

+0

谢谢,就是这样。你能帮我调用.HasColumnName()吗?这很难,因为.Property有很多覆盖,我不知道如何调用正确的。 – powlette 2012-03-19 17:23:29

+0

当然,我在上面。 – 2012-03-19 17:49:33

0

IMO这是不是流利的API的预期目的。 Fluent API的全部目的是提供更易读易用的配置方式,同时为您提供编译时安全性。我用这种方法看不到这一点。

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

+0

嗯,我有一百个属性的类,其中没有一个对应表中的列,我不想明确地忽略它们。更好的办法是自己检查table/model/xml配置并动态调用.Ignore。 – powlette 2012-03-19 16:05:45

+0

试图适应不是为此目的而设计的东西只会让事情变得更糟。最好有一组EF实体映射到您的业务类。 – Eranga 2012-03-19 16:20:34