如何从EDM模型中确定Principal端与Dependent端,无需反射访问私有字段
EF6 无反射区分关联关系Principal/Dependent端方案
固定判定规则(100%符合EF内部实现)
EF元数据系统有公开的固定约定,不需要反射访问私有字段即可准确区分两端:
- 带外键约束的关联(存在
ReferentialConstraint):ReferentialConstraint.FromRole固定对应 Principal端,ReferentialConstraint.FromProperties存储Principal端的主键属性ReferentialConstraint.ToRole固定对应 Dependent端,ReferentialConstraint.ToProperties存储Dependent端的外键属性
该对应关系和EF内部私有字段PrincipalEnd/DependentEnd的取值完全一致,无任何例外情况。
- 无外键约束的独立关联(无
ReferentialConstraint):
取关联的两个AssociationEndMember,按多重性判断:- 多重性为
1/0..1的一端为Principal端,多重性为*的一端为Dependent端 - 一对一关联两端多重性均为
1/0..1时,DeleteBehavior = Cascade的一端为Principal端,另一端为Dependent端
- 多重性为
代码实现示例
using System.Data.Entity.Core.Metadata.Edm; // metadataWorkspace 为你已经初始化的元数据工作区实例 foreach (var association in metadataWorkspace.GetItems<AssociationType>(DataSpace.CSpace)) { AssociationEndMember principalEnd; AssociationEndMember dependentEnd; IEnumerable<EdmProperty> principalKeys; IEnumerable<EdmProperty> dependentForeignKeys; if (association.ReferentialConstraints.Any()) { var constraint = association.ReferentialConstraints.First(); principalEnd = constraint.FromRole as AssociationEndMember; dependentEnd = constraint.ToRole as AssociationEndMember; principalKeys = constraint.FromProperties; dependentForeignKeys = constraint.ToProperties; } else { var end1 = association.AssociationEndMembers[0]; var end2 = association.AssociationEndMembers[1]; if (end1.RelationshipMultiplicity == RelationshipMultiplicity.Many) { principalEnd = end2; dependentEnd = end1; } else if (end2.RelationshipMultiplicity == RelationshipMultiplicity.Many) { principalEnd = end1; dependentEnd = end2; } else { // 一对一关联判定 principalEnd = end1.DeleteBehavior == OperationAction.Cascade ? end1 : end2; dependentEnd = principalEnd == end1 ? end2 : end1; // 可选:如果无级联删除,也可以通过两端实体主键是否被用作关联外键补充判断 } principalKeys = principalEnd.GetEntityType().KeyMembers.Cast<EdmProperty>(); dependentForeignKeys = Enumerable.Empty<EdmProperty>(); } // 后续处理你的外键信息逻辑 }
准确率说明
你看到的相关方案完全基于EF官方元数据约定实现,准确率为100%,和EF内部读取私有字段的判断逻辑没有任何差异,不需要额外验证。
内容的提问来源于stack exchange,提问作者LINQ2Vodka
相关产品推荐
相关产品推荐

