【问题标题】:Dynamic Fluent Mapping with EF4.1使用 EF4.1 进行动态流利映射
【发布时间】:2012-03-19 15:16:54
【问题描述】:

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

【问题讨论】:

    标签: reflection entity-framework-4.1 linq-expressions


    【解决方案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&lt;T&gt; 类型)。

    【讨论】:

    • 谢谢,就是这样。你能帮我打电话给 .HasColumnName() 吗?这更难,因为 .Property 有很多覆盖,我不确定如何调用正确的。
    【解决方案2】:

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

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

    【讨论】:

    • 好吧,我有一百个属性的类,没有一个对应于表中的列,我不想明确地忽略它们。最好自己检查 table/model/xml 配置并动态调用 .Ignore。
    • 试图适应并非为此目的而设计的东西只会让事情变得更糟。最好有一组将映射到您的业务类的 EF 实体。
    猜你喜欢
    • 1970-01-01
    • 2010-11-06
    • 2014-06-19
    • 1970-01-01
    • 1970-01-01
    • 2010-12-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-25
    相关资源
    最近更新 更多