[英]How can I find the Id property or properties related to a navigational property?
For a project I'm working with Entity Framework and I'd like to be able to enumerate all navigational properties for a given object instance (assuming it's an object generated by EF). 对于我正在使用Entity Framework的项目,我希望能够枚举给定对象实例的所有导航属性(假设它是由EF生成的对象)。 From there I'd like to get the related Id property for every navigational property.
从那里我想获得每个导航属性的相关Id属性。
For example, if I get an instance of the class Person
, I want to be able to find it's navigational properties called Address
and Boss
. 例如,如果我得到
Person
类的实例,我希望能够找到它的名为Address
and Boss
的导航属性。 For those two navigational properties I want to then "lookup" the related Id properties called AddressId
and BossId
. 对于那两个导航属性,我想“查找”名为
AddressId
和BossId
的相关Id属性。
I need those Id properties so I can run queries on a different database which does not have the same foreign keys but does have exactly the same Ids. 我需要那些Id属性,所以我可以在不具有相同外键但具有完全相同的ID的不同数据库上运行查询。
So far I have figured out a way to get the RelationshipManager for a random object instance generated by EF. 到目前为止,我已经想出了一种方法来获取由EF生成的随机对象实例的RelationshipManager 。 And while debugging I can get to the foreign key relations via the Manager's
Relationships
property. 在调试时,我可以通过Manager的
Relationships
属性获取外键关系。 But I can only get as far as the navigational property name. 但我只能获得导航属性名称。 So I can see there's a
FK_Person_Address
which is related to the navigational property called Address
but I can't find the AddressId
. 所以我可以看到有一个
FK_Person_Address
与名为Address
的导航属性相关,但我找不到AddressId
。
So my question is, how can I dynamically (with no knowledge of the Person
class' layout) discover the AddressId
property which is related to Address
? 所以我的问题是,我怎样才能动态地(不知道
Person
类的布局)发现与Address
相关的AddressId
属性?
I am aware the Foreign Key relationship might have the Id property on the other side of the relation ( Boss
pointing to Person
in stead of Person
having a BossId
). 我知道外键关系可能在关系的另一端有Id属性(
Boss
指向Person
而不是Person
有BossId
)。 In that case, I'd still like to discover that Boss
has a PersonId
when I'm inspecting an instance of Person
. 在那种情况下,当我正在检查一个
Person
实例时,我仍然想发现Boss
有一个PersonId
。
This will give you a dictionary with all navigation properties as Key and all related properties as Value (the value might be a property from the other entity) 这将为您提供一个字典,其中所有导航属性为Key,所有相关属性为Value(该值可能是其他实体的属性)
Add these to your DBContext class and call db.GetForeignKeyProperties<Person>()
将这些添加到您的DBContext类并调用
db.GetForeignKeyProperties<Person>()
The result will be something like: 结果将是这样的:
"Address" - "AddressID" “地址” - “地址ID”
"Boss" - "Person.BossID" “老板” - “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;
}
Here's a method that returns key values of know entity objects: 这是一个返回已知实体对象的键值的方法:
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));
}
This method uses the underlying ObjectContext
API to obtain ObjectStateEntry
objects that belong to each entity object. 此方法使用基础
ObjectContext
API来获取属于每个实体对象的ObjectStateEntry
对象。 The EntityKey
contains the key value(s) of an entity as a key-value pair. EntityKey
包含实体的键值作为键值对。 (Entities with composite keys have more than one key value.) (具有复合键的实体具有多个键值。)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.