我有一个带参数T的泛型方法,其中T是EF模型中的实体类型。 我需要获得此类型的识别字段的名称。 我看到这篇文章:Is there a way to get entity id-field's name by reflection or whatever? 但我无法理解Tevin谈论 EntitySetBase 和 EntityTypeBase 类型时所说的内容。 如果 EntityTypeBase 是模型中某个实体的类型,那么EF6没有属性 KeyMembers 。
答案 0 :(得分:20)
我认为只有通过反思才能获得主键。
首先,让我们看看EF如何确定哪些属性(无论顺序/优先级是哪个)
主键的实体框架约定是:
- 您的班级定义了名称为“ID”或“Id”
的媒体资源- 或类名后跟“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
函数,一切都被封装。您可以查看source code。 EF中的所有内容都取决于ObjectContext
,并且一旦ObjectContext
被调用,例如这行代码,
((IObjectContextAdapter)context).ObjectContext
然后将建立与数据库的连接,您可以使用profiler进行检查。这是源代码的代码摘录。
public override ObjectContext ObjectContext
{
get
{
Initialize();
return ObjectContextInUse;
}
}
public void Initialize()
{
InitializeContext();
InitializeDatabase();
}
因此,目前获取主键的唯一可能方法是通过对象集,实体集,关键成员等,如this post中所述
var keyNames = set.EntitySet.ElementType.KeyMembers.Select(k => k.Name);