entity framework代码第一。 find主键

如何find一个类的哪个属性是entity framework代码第一个实体POCO的主键?

请注意Id / class name +“Id”的string匹配是一个不好的select。 必须有一些方法来挖掘entity framework所使用的约定,并可靠地获得关键属性。

提前致谢。

您可以要求映射元数据来获取关键属性的名称(可以有多个):

ObjectContext objectContext = ((IObjectContextAdapter)dbContext).ObjectContext; ObjectSet<YourEntity> set = objectContext.CreateObjectSet<YourEntity>(); IEnumerable<string> keyNames = set.EntitySet.ElementType .KeyMembers .Select(k => k.Name); 

一旦你有密钥名称,你可以使用reflection来访问它们的值。

正如你所看到的那样,这个方法会恢复到ObjectContext API,因为DbContext API只适用于那些不需要映射元数据等细节的简单场景。

如果它帮助任何人,我需要能够做到这一点,而不必事先知道types(所以我不能轻易做CreateObjectSet<YourEntity>()因为我不知道YourEntity ),所以我能够适应@拉迪斯拉夫的解决scheme如下:

 // 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需要types名称和命名空间的string,而不是System.Type,但这是我能find的最好的。

在EF 6.1中有一个Db()扩展方法,使这更容易。

  • Nuget: https ://www.nuget.org/packages/EntityFramework.MappingAPI/(v6.1.0.9)
  • 命名空间: EntityFramework.MappingAPI.Extensions.MappingApiExtensions

例:

 public static IEnumerable<string> GetPrimaryKeyPropertyNames(DbContext db, Type entityType) { return db.Db(entityType).Pks.Select(x => x.PropertyName); } 

由于Table Per Type的inheritance,我对上述两种方法都有问题。 我的工作版本(基于@ S'pht'Kr的解决scheme,但使用DataSpace.OSpace而不是DataSpace.CSpace出于这个原因)如下:

  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的答案的变体,只需要在运行时知道types,而不需要在编译时知道types。 也像用户rashleighp,用户S'pht'Kr的解决scheme不适合我,但他的解决scheme确实工作。 下面,我通过提供一个更简单的答案来帮助我解决这个问题。 不过,我刚刚了解了用户anjdreas的解决scheme,那就是我将要使用的解决scheme。

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