如何找到与导航属性相关的 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 的实例,我希望能够找到它的导航属性,称为AddressBoss。对于这两个导航属性,我想“查找”名为 AddressIdBossId 的相关 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 属性或属性?的主要内容,如果未能解决你的问题,请参考以下文章

Angular2如何导航到用id属性标识的页面的某些部分

当延迟加载禁用时,如何通过实体框架仅将导航属性的特定属性包含到查询中?

如何修复可能的未处理承诺拒绝(id:0)?以及如何修复无法读取未定义的属性“导航”?

2017-03-31JS-DOM操作:操作属性彩虹导航栏定时器操作内容创建元素并添加操作相关元素

C#,Winform绑定实体框架(Entity Framework)的实体,如何去掉或隐藏导航属性?

LINQ to SQL查询基于使用外键与使用内置导航属性成功或失败