有没有办法在运行时查看Entity Framework Code First的列映射?

djd*_*d87 5 c# reflection entity-framework ef-code-first

我正在尝试编写Entity Framework Code First的附加组件,我需要一种方法来在运行时获取模型列的配置.例如,这是对码设置OnModelCreating由DbModelBuilder:

builder.Entity<NwdEmployee>()
    .Property(n => n.ReportsToID).HasColumnName("ReportsTo");
Run Code Online (Sandbox Code Playgroud)

完成后,EntityFramework知道我的属性的名称与表中的列名不同,但是如何在运行时找到该字符串"ReportsTo"与ReportsToID我自己相关?理想情况下,我正在尝试编写如下方法:

public string GetMappedColumnName<TFrom>(DbContext context, 
    Func<TFrom, object> selector);
Run Code Online (Sandbox Code Playgroud)

将使用如下:

string mappedColumnName = GetMappedColumnName<NwdEmployee>(context, 
    x => x.ReportsToID);
Run Code Online (Sandbox Code Playgroud)

我只是不知道在DbContext中找到映射列名的位置.它们甚至可以访问吗?

Lad*_*nka 4

理论上是的。实际上我不确定,因为通过简单的测试,我无法在运行时获取这些信息 - 我在调试器中看到它们,但我无法获取它们,因为我需要使用的类型是实体框架中的内部类型。

理论。所有映射信息在运行时都可用,但不能通过反射获得。它们存储在类的实例中,MetadataWorkspace该类绝对不是为直接使用而设计的,因为与此类的每次交互都需要在调试器中花费一些时间,然后才能找到如何获取所需的数据。无法通过 DbContext API 访问此数据。您必须转换DbContext回ObjectContext并访问MetadataWorkspace.

ObjectContext objContext = ((IObjectContextAdapter)dbContext).ObjectContext;
GlobalItem storageMapping = objContext.MetadataWorkspace.GetItem<GlobalItem>("NameOfYourContextClass", DataSpace.CSSpace);
Run Code Online (Sandbox Code Playgroud)

现在storageMapping是System.Data.Mapping.StorageEntityContainerMapping类的实例,它是internal. 据我了解,这个类应该是 MSL = 存储和概念模型之间映射的运行时表示。

如果您使用调试器,您可以探索实例,您将找到有关属性和列之间映射的信息(其嵌套相当深),因此您也可以使用反射来获取它们,但它是对您不拥有的类的非公共接口的反射因此任何 .NET 框架补丁/修复/更新都可能会破坏您的应用程序。

  • 为什么获取这些信息如此复杂?EF 在批量插入方面的性能确实很差。您可以使用自定义 EntityDataReader 和 SqlBulkCopy 来完成工作,但前提是您拥有这些映射。我不想一遍又一遍地对这些映射进行硬编码,只是为了在这些映射之一发生更改时必须进行手动修复。我知道,OR/M 与批量数据无关。但请考虑从其他系统导入,您必须在其中进行批量插入。现在怎么办? (2认同)