获取EF代码第一实体的外键约束列表

时间:2015-02-17 15:30:10

标签: c# entity-framework

我正在尝试在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...
     }
}

1 个答案:

答案 0 :(得分:3)

我知道这可能是一个老问题,但我会在这里留下解决方案以防万一。获得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;
}