首先是实体框架代码.查找主键

Sle*_*ith 33 ef-code-first entity-framework-4.1

如何找到类的哪个属性是实体框架代码优先实体POCO的主键?

请注意Id/class name +"Id"的字符串匹配是一个不好的选择.必须有一些方法来挖掘Entity Framework使用的约定并可靠地获取密钥属性.

提前致谢.

Lad*_*nka 59

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

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

拥有密钥名称后,您可以使用反射来访问其值.

正如您所看到的,该方法将恢复为ObjectContext API,因为DbContext API仅适用于您不需要处理映射元数据等详细信息的简单方案.

  • 谢谢。标记为答案。我确实想评论说,向上下文类(例如,IYourDataContext)添加一个接口并将 IObjectContextAdapter 继承到该 IYourDataContext 是一个更好的主意。这样你就不必投射它。 (2认同)

S'p*_*'Kr 26

如果它对任何人都有帮助,我需要能够在事先不知道类型的情况下做到这一点(所以我不能轻易做到,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;
Run Code Online (Sandbox Code Playgroud)

看起来很奇怪,MetadataWorkspace.GetType需要类型名称和命名空间的字符串,而不是System.Type,但这是我能找到的最好的.


ang*_*sen 14

在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);
}
Run Code Online (Sandbox Code Playgroud)

  • @anjdreas或者是因为它[现在花费700美元](http://entityframework-extensions.net/?z=nuget&y=mappingapi). (3认同)
  • 链接的包已过时,不再在NuGet上列出 (2认同)

ras*_*ghp 9

由于Table Per Type继承,我对上述两种方法都有问题.我的工作版本(基于@ S'pht'Kr的解决方案,但因此使用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;
        }
Run Code Online (Sandbox Code Playgroud)