如何找到与导航属性相关的Id属性?

对于我正在使用Entity Framework的项目,我希望能够枚举给定对象实例的所有导航属性(假设它是由EF生成的对象)。 从那里我想获得每个导航属性的相关Id属性。

例如,如果我得到Person类的实例,我希望能够找到它的名为Address and Boss的导航属性。 对于那两个导航属性,我想“查找”名为AddressIdBossId的相关Id属性。

我需要那些Id属性,所以我可以在不同的数据库上运行查询,该数据库没有相同的外键但具有完全相同的ID。

到目前为止,我已经想出了一种方法来获取由EF生成的随机对象实例的RelationshipManager 。 在调试时,我可以通过Manager的Relationships属性获取外键关系。 但我只能获得导航属性名称。 所以我可以看到有一个FK_Person_Address与名为Address的导航属性相关,但我找不到AddressId

所以我的问题是,我如何动态地(不知道Person类的布局)发现与Address相关的AddressId属性?

我知道外键关系可能在关系的另一端有Id属性( Boss指向Person而不是PersonBossId )。 在那种情况下,当我正在检查一个Person实例时,我仍然想发现Boss有一个PersonId

这将为您提供一个字典,其中所有导航属性为Key,所有相关属性为Value(该值可能是其他实体的属性)

将这些添加到您的DBContext类并调用db.GetForeignKeyProperties()

结果将是这样的:

“地址” – “地址ID”

“老板” – “Person.BossID”

 public Dictionary GetForeignKeyProperties() { EntityType table = GetTableEntityType(); Dictionary foreignKeys = new Dictionary(); foreach (NavigationProperty np in table.NavigationProperties) { var association = (np.ToEndMember.DeclaringType as AssociationType); var constraint = association.ReferentialConstraints.FirstOrDefault(); if (constraint != null && constraint.ToRole.GetEntityType() == table) foreignKeys.Add(np.Name, constraint.ToProperties.First().Name); if (constraint != null && constraint.FromRole.GetEntityType() == table) foreignKeys.Add(np.Name, constraint.ToProperties.First().DeclaringType.Name+"."+constraint.ToProperties.First().Name); } return foreignKeys; } private EntityType GetTableEntityType() { return GetTableEntityType(typeof(DBType)); } private EntityType GetTableEntityType(Type DBType) { ObjectContext objContext = ((IObjectContextAdapter)this).ObjectContext; MetadataWorkspace workspace = objContext.MetadataWorkspace; EntityType table = workspace.GetEdmSpaceType((StructuralType)workspace.GetItem(DBType.FullName, DataSpace.OSpace)) as EntityType; return table; } 

这是一个返回已知实体对象的键值的方法:

 IEnumerable> GetKeyValues(DbContext db, IEnumerable entities) where T : class { var oc = ((IObjectContextAdapter)db).ObjectContext; return entities.Select (e => oc.ObjectStateManager.GetObjectStateEntry(e)) .Select(objectStateEntry => objectStateEntry.EntityKey) .Select(ek => ek.EntityKeyValues .ToDictionary (x => x.Key, y => y.Value)); } 

此方法使用基础ObjectContext API来获取属于每个实体对象的ObjectStateEntry对象。 EntityKey包含实体的键值作为键值对。 (具有复合键的实体具有多个键值。)