如何找到与导航属性相关的 Id 属性或属性?
Posted
技术标签:
【中文标题】如何找到与导航属性相关的 Id 属性或属性?【英文标题】:How can I find the Id property or properties related to a navigational property? 【发布时间】:2015-11-09 05:35:40 【问题描述】:对于我正在使用实体框架的项目,我希望能够枚举给定对象实例的所有导航属性(假设它是由 EF 生成的对象)。从那里我想为每个导航属性获取相关的 Id 属性。
例如,如果我得到一个类Person
的实例,我希望能够找到它的导航属性,称为Address
和Boss
。对于这两个导航属性,我想“查找”名为 AddressId
和 BossId
的相关 Id 属性。
我需要这些 Id 属性,以便我可以在不同的数据库上运行查询,该数据库没有相同的外键但确实具有完全相同的 Id。
到目前为止,我已经找到了一种方法来获取 EF 生成的随机对象实例的 RelationshipManager。在调试时,我可以通过 Manager 的 Relationships
属性获得外键关系。但我只能得到导航属性名称。所以我可以看到有一个FK_Person_Address
与名为Address
的导航属性相关,但我找不到AddressId
。
所以我的问题是,我怎样才能动态地(不知道Person
类的布局)发现与Address
相关的AddressId
属性?
我知道外键关系可能在关系的另一端具有 Id 属性(Boss
指向 Person
而不是 Person
具有 BossId
)。在这种情况下,当我检查Person
的实例时,我仍然想发现Boss
有一个PersonId
。
【问题讨论】:
你是先用代码生成表格吗? 不,数据库优先 你是在构建还是运行时想要这个? 由于模型在运行时不会改变,并且整个模型在编译时是已知的,所以构建或运行时都应该没问题。 【参考方案1】:这将为您提供一个字典,其中所有导航属性为 Key,所有相关属性为 Value(该值可能是来自其他实体的属性)
将这些添加到您的 DBContext 类并调用 db.GetForeignKeyProperties<Person>()
结果会是这样的:
“地址”-“地址 ID”
“老板”-“Person.BossID”
public Dictionary<string,string> GetForeignKeyProperties<DBType>()
EntityType table = GetTableEntityType<DBType>();
Dictionary<string, string> foreignKeys = new Dictionary<string, string>();
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<DBType>()
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<EntityType>(DBType.FullName, DataSpace.OSpace)) as EntityType;
return table;
【讨论】:
好先生,这正是我正在寻找的答案,谢谢! 乐于助人。不久前我也花了一些时间来搜索如何做到这一点。 自引用崩溃:尝试将相同的名称添加到字典两次。无论您想要“从”还是“到”FK,我都会添加一个参数。【参考方案2】:这是一个返回已知实体对象的键值的方法:
IEnumerable<IDictionary<string,object>> GetKeyValues<T>(DbContext db,
IEnumerable<T> 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
包含实体的键值作为键值对。 (具有复合键的实体具有多个键值。)
【讨论】:
感谢您的回答,但这不是我要找的。我实际上已经将EntityKeyValues
用于不同的目的。我想获取所有外键的列表,而不是您的代码提供的主键。或者EntityKeyValues
也可以用来检索外键?
好的,我误解了你问题的查找部分。你想要的不太明显,我现在不知道有什么办法,也许以后再说。以上是关于如何找到与导航属性相关的 Id 属性或属性?的主要内容,如果未能解决你的问题,请参考以下文章
当延迟加载禁用时,如何通过实体框架仅将导航属性的特定属性包含到查询中?
如何修复可能的未处理承诺拒绝(id:0)?以及如何修复无法读取未定义的属性“导航”?
2017-03-31JS-DOM操作:操作属性彩虹导航栏定时器操作内容创建元素并添加操作相关元素