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



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

例如,如果我得到一个类Person的实例,我希望能够找到它的导航属性AddressBoss。对于这两个导航属性,我想"查找"相关的Id属性AddressIdBossId

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

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

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

我知道外键关系可能在关系的另一边具有Id属性(Boss指向Person,而不是Person具有BossId)。在这种情况下,当我检查Person的实例时,我仍然想发现BossPersonId

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

将这些添加到DBContext类中并调用db.GetForeignKeyProperties<Person>()

结果类似于:

Address - AddressID

"老板"-"人。"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;
}

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

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以键值对的形式包含实体的键值。(具有组合键的实体有多个键值)

相关内容

  • 没有找到相关文章

最新更新