EntityFramework 6 如何使用反射获取自增字段?

19
我有一个通用的方法,其中类型参数T是EF模型中实体的类型。我需要获取此类型中标识字段的名称。 我看到了这篇文章:Is there a way to get entity id-field's name by reflection or whatever?但我不理解Tevin在谈论EntitySetBaseEntityTypeBase类型时在说什么。 如果EntityTypeBase是模型中某个实体的类型,那么EF6就没有KeyMembers属性。

请查看此帖子 - Yuliam Chandra
@YuliamChandra 感谢回复。所以,KeyMembers 是从上下文中获取的,我理解代码创建了一个使用一些系统资源的实体集。是否有其他途径可以通过反射获得关键字段名称? - Jonik
这不是纯粹的反射,需要先使用在帖子中解释的edm获取键名,因为可以使用约定Fluent Api将关键属性配置为关键字段,这些内容仅通过反射无法获取。 - Yuliam Chandra
无论如何,所有的数据都在DbContext中。除了使用CreateObjectSet<T>()方法创建ObjectSet<T>之外,是否没有其他方法可以获取键名? - Jonik
1个回答

32

我认为仅通过反射无法获取主键。

首先,让我们了解EF如何确定哪些属性将是主键,而不考虑顺序/优先级。

主键的Entity Framework约定是:

  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));

我们可以使用CustomAttributes并比较属性类型。

var key = type.GetProperties().FirstOrDefault(p => 
    p.CustomAttributes.Any(attr => attr.AttributeType == typeof(KeyAttribute)));

这是难以实现的一个,modelBuilder被封装在OnModelCreating中,即使我们将modelBuilder保存在字段/属性中,也很难从HasKey函数中提取密钥,因为一切都被封装。 你可以查看源代码。而且EF中的所有内容都依赖于ObjectContext,一旦调用了ObjectContext,例如以下代码行:

((IObjectContextAdapter)context).ObjectContext

然后将建立与数据库的连接,您可以使用分析器进行检查。下面是源代码的代码摘录。

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

public void Initialize()
{
    InitializeContext();
    InitializeDatabase();
}

因此,目前唯一获取主键的方法是通过对象集、实体集、关键成员等方式,详见此帖子

var keyNames = set.EntitySet.ElementType.KeyMembers.Select(k => k.Name);

很棒的答案!关于[KeyAttribute],最好使用“Where”而不是“FirstOrDefault”,因为我的一些实体具有复合键。 - bunjeeb

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接