我有一个通用的方法,其中类型参数T是EF模型中实体的类型。我需要获取此类型中标识字段的名称。
我看到了这篇文章:Is there a way to get entity id-field's name by reflection or whatever?但我不理解Tevin在谈论EntitySetBase和EntityTypeBase类型时在说什么。
如果EntityTypeBase是模型中某个实体的类型,那么EF6就没有KeyMembers属性。
我认为仅通过反射无法获取主键。
首先,让我们了解EF如何确定哪些属性将是主键,而不考虑顺序/优先级。
主键的Entity Framework约定是:
- 您的类定义一个名为“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
函数中提取密钥,因为一切都被封装。 你可以查看源代码。而且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);