如何找到Entity Framework Code First实体POCO的主键属性?
请注意,对于Id /类名+“Id”的字符串匹配是不好的选择。必须有某种方法来挖掘Entity Framework使用的约定并可靠地获取关键属性。
先行致谢。
如何找到Entity Framework Code First实体POCO的主键属性?
请注意,对于Id /类名+“Id”的字符串匹配是不好的选择。必须有某种方法来挖掘Entity Framework使用的约定并可靠地获取关键属性。
先行致谢。
您可以询问映射元数据以获取关键属性的名称(可能有多个):
ObjectContext objectContext = ((IObjectContextAdapter)dbContext).ObjectContext;
ObjectSet<YourEntity> set = objectContext.CreateObjectSet<YourEntity>();
IEnumerable<string> keyNames = set.EntitySet.ElementType
.KeyMembers
.Select(k => k.Name);
一旦你有键名,你就可以使用反射来访问它们的值。
正如你所看到的,这种方法会回归到ObjectContext API,因为DbContext API仅适用于简单情况,您不需要担心像映射元数据这样的细节。
如果有人需要帮助,我需要在不事先知道类型的情况下执行此操作(所以我不能轻松地执行CreateObjectSet<YourEntity>()
,因为我不知道YourEntity
),所以我能够将@Ladislav的解决方案调整为以下内容:
// variable "type" is a System.Type passed in as a method parameter
ObjectContext objectContext = ((IObjectContextAdapter)this.context).ObjectContext;
IEnumerable<string> retval = (IEnumerable<string>)objectContext.MetadataWorkspace
.GetType(type.Name, type.Namespace, System.Data.Entity.Core.Metadata.Edm.DataSpace.CSpace)
.MetadataProperties
.Where(mp => mp.Name == "KeyMembers")
.First()
.Value;
看起来有些奇怪,MetadataWorkspace.GetType
需要类型名称和命名空间的字符串,而不是System.Type,但这是我能找到的最好的方法。
在 EF 6.1 中有一个 Db()
扩展方法,使这个过程变得更容易。
EntityFramework.MappingAPI.Extensions.MappingApiExtensions
示例:
public static IEnumerable<string> GetPrimaryKeyPropertyNames(DbContext db, Type entityType)
{
return db.Db(entityType).Pks.Select(x => x.PropertyName);
}
protected IEnumerable<string> GetKeyPropertyNames()
{
var objectContext = ((System.Data.Entity.Infrastructure.IObjectContextAdapter) this.Context).ObjectContext;
return GetKeyPropertyNames(typeof (TEntity), objectContext.MetadataWorkspace);
}
private static IEnumerable<string> GetKeyPropertyNames(Type type, MetadataWorkspace workspace)
{
EdmType edmType;
if (workspace.TryGetType(type.Name, type.Namespace, DataSpace.OSpace, out edmType))
{
return edmType.MetadataProperties.Where(mp => mp.Name == "KeyMembers")
.SelectMany(mp => mp.Value as ReadOnlyMetadataCollection<EdmMember>)
.OfType<EdmProperty>().Select(edmProperty => edmProperty.Name);
}
return null;
}
像用户 rashleighp 一样,我也想要一个用户 Ladislav Mrnka 答案的变体,它只需要在运行时知道类型,而不需要在编译时知道类型。与用户 rashleighp 一样,用户 S'pht'Kr 的解决方案对我无效,但他的解决方案有效。下面,我通过提供他的答案的一个更简单的版本来为这个对话做出贡献。但是,我刚刚了解到用户 anjdreas 的解决方案,我将使用那个。
// variable "type" is a System.Type passed in as a method parameter
((IObjectContextAdapter)context)
.ObjectContext
.MetadataWorkspace
.GetItem<EntityType>(type.FullName, DataSpace.OSpace)
.KeyProperties
.Select(p => p.Name);