获取EF代码优先实体的外键约束列表



我正试图在EF代码优先的场景中确定实体上的外键

到目前为止,我的代码告诉我外键所关联的表(或者更确切地说是导航属性),但我需要表示两端关系的属性(一个简单的字符串就可以了):

public void DetermineForiegnKeys<T>()
{
    entitySet = ((IObjectContextAdapter)dbbuilder.s200).ObjectContext.CreateObjectSet<T>().EntitySet;
    var nps = entitySet.Value.ElementType.NavigationProperties;
    foreach (var np in nps)
    {
        var otherTableType = ((RefType)np.FromEndMember.TypeUsage.EdmType).ElementType;
        var otherIsFrom = true;
        if (otherTableType.Name.Equals(typeof(T).Name))
        {
            otherTableType = ((RefType)np.ToEndMember.TypeUsage.EdmType).ElementType;
            otherIsFrom = false;
        }
        //how do I get the property names on this entity (T) and the other??
        // just the IDs, not the virtual properties...
     }
}

我知道这可能是一个老问题,但我会在这里留下一个解决方案以防万一。一旦您获得了NavigationProperty,就可以使用GetDependentProperties来获得外键列表。棘手的部分是,该方法只为CSpace类型返回键。因此,我们必须将代理类型转换为CSpace类型。

public static string[] GetForeignKeys(DbContext context, Type type)
{
    StructuralType edmType = GetCSpaceType(context, type);
    var members = edmType
                        .MetadataProperties
                        .Where(mp => mp.Name == "Members")
                        .FirstOrDefault();
    if (members != null && members.Value != null)
    {
        List<NavigationProperty> navProps = ((ICollection<EdmMember>)members.Value)
                                            .Where(m => m.BuiltInTypeKind == BuiltInTypeKind.NavigationProperty)
                                            .Cast<NavigationProperty>()
                                            .Where(p =>
                                                ((AssociationType)p.RelationshipType).IsForeignKey
                                            )
                                            .ToList();
        List<EdmProperty> foreignKeys = navProps
                                        .SelectMany(p => p.GetDependentProperties())
                                        .ToList();
        return foreignKeys.Select(p => p.Name).ToArray();
    }
    return null;
}
private static StructuralType GetCSpaceType(DbContext context, Type type)
{
    MetadataWorkspace workspace = ((IObjectContextAdapter)context).ObjectContext.MetadataWorkspace;
    EdmType ospaceType = workspace.GetType(type.Name, type.Namespace, DataSpace.OSpace);
    return workspace.GetEdmSpaceType((StructuralType)ospaceType);
}

更新:为了更具体地获取特定类型的相关实体的外键,您可以执行以下操作:

public static PropertyInfo GetForeignKey(DbContext context, Type type, Type related)
{
    StructuralType edmType = GetCSpaceType(context, type);
    StructuralType parentEdmType = GetCSpaceType(context, related);
    var members = edmType
                        .MetadataProperties
                        .Where(mp => mp.Name == "Members")
                        .FirstOrDefault();
    if (members != null && members.Value != null)
    {
        List<NavigationProperty> navProps = ((ICollection<EdmMember>)members.Value)
                                            .Where(m => m.BuiltInTypeKind == BuiltInTypeKind.NavigationProperty)
                                            .Cast<NavigationProperty>()
                                            .Where(p =>
                                                ((AssociationType)p.RelationshipType).IsForeignKey
                                            )
                                            .ToList();
        NavigationProperty navProp = navProps
                                        .FirstOrDefault(p => ((RefType)p.ToEndMember.TypeUsage.EdmType).ElementType.FullName == parentEdmType.FullName);
        if (navProp != null)
        {
            var dependent = navProp.GetDependentProperties().ToList();
            if (dependent.Count > 0)
            {
                return type.GetProperty(dependent[0].Name);
            }
        }
    }
    return null;
}

最新更新