EntityFramework 6如何使用反射获取identity-field?

Jon*_*nik 16 c# reflection entity-framework entity-framework-6

我有一个类型参数为T的泛型方法,其中T是EF模型中的实体类型.我需要获得此类型的识别字段的名称.我看到这篇文章:有没有办法通过反射或其他方式获取实体id-field的名称? 但我无法理解Tevin谈论EntitySetBaseEntityTypeBase类型时所说的内容.如果EntityTypeBase是模型中某个实体的类型,那么EF6没有属性KeyMembers.

Yul*_*dra 23

我认为只有通过反射才能获得主键.

首先,让我们了解EF如何确定哪些属性将成为主键,而不管顺序/优先级如何

主键的实体框架约定是:

  1. 您的类定义了一个名称为"ID"或"Id"的属性
  2. 或类名后跟"ID"或"Id"

我们可以使用GetProperties和比较属性名称.

var key = type.GetProperties().FirstOrDefault(p => 
    p.Name.Equals("ID", StringComparison.OrdinalIgnoreCase) 
    || p.Name.Equals(type.Name + "ID", StringComparison.OrdinalIgnoreCase));
Run Code Online (Sandbox Code Playgroud)

我们可以使用CustomAttributes和比较属性类型.

var key = type.GetProperties().FirstOrDefault(p => 
    p.CustomAttributes.Any(attr => attr.AttributeType == typeof(KeyAttribute)));
Run Code Online (Sandbox Code Playgroud)

这是一个很难做到的,modelBuilder被封装在中OnModelCreating,即使我们将modelBuilder某个地方保存为字段/属性,仍然难以从HasKey函数中提取密钥,所有内容都被封装.您可以查看源代码.EF中的所有内容都依赖于ObjectContext并且一旦ObjectContext被调用,例如这行代码,

((IObjectContextAdapter)context).ObjectContext
Run Code Online (Sandbox Code Playgroud)

然后将建立与数据库的连接,您可以使用profiler进行检查.这是源代码的代码摘录.

public override ObjectContext ObjectContext
{
    get
    {
        Initialize();
        return ObjectContextInUse;
    }
}

public void Initialize()
{
    InitializeContext();
    InitializeDatabase();
}
Run Code Online (Sandbox Code Playgroud)

因此,目前唯一可行的办法让主键(一个或多个)是通过对象集,实体集,主要成员等在解释这个岗位

var keyNames = set.EntitySet.ElementType.KeyMembers.Select(k => k.Name);
Run Code Online (Sandbox Code Playgroud)