获取给定EntityType的导航属性

Lei*_*ang 9 c# linq ado.net entity-framework

我使用的是VS2010,EF4.0.需要如下功能.

private string[] GetNaviProps(Type entityType)//eg typeof(Employee)
{
    NorthwindEntities en = new NorthwindEntities();
    //here I return all Properties only for example
    return entityType.GetProperties().Select(p=>p.Name).ToArray();
    //should return Orders,Territories...
}
Run Code Online (Sandbox Code Playgroud)

我已经检查了这个,但IObjectContextAdapter在EF6.0和.net4.5中看起来很像.我试着像它一样替换它

var workspace = en.MetadataWorkspace;
Run Code Online (Sandbox Code Playgroud)

所以它可以编译,但是然后在第3行抛出异常.
有帮助吗?

Mar*_*zek 13

您可以过滤GetProperties结果以仅获取实现ICollection或实现的结果IEnumerable.但是,您应该记住该string实现IEnumerable,因此您必须添加其他检查以不返回string属性.

return entityType.GetProperties()
                 .Where(p => typeof(IEnumerable).IsAssignableFrom(p.PropertyType) && p.PropertyType != string)
                 .Select(p => p.Name)
                 .ToArray();
Run Code Online (Sandbox Code Playgroud)

更新

您也可以更改Where谓词以比较命名空间.它还返回1:1导航属性:

private static string[] GetNaviProps(Type entityType)//eg typeof(Employee)
{
    return entityType.GetProperties()
                     .Where(p => (typeof(IEnumerable).IsAssignableFrom(p.PropertyType) && p.PropertyType != typeof(string)) ||  p.PropertyType.Namespace == entityType.Namespace)
                     .Select(p => p.Name)
                     .ToArray();
}
Run Code Online (Sandbox Code Playgroud)


cod*_*Dom 5

基于这个答案

    private static List<PropertyInfo> GetNavigationProperties(Type t)
    {

        var navigationProperties = new List<PropertyInfo>();

        if (t.BaseType != null && t.Namespace == "System.Data.Entity.DynamicProxies") {
            t = t.BaseType;
        }

        string fkName = t.Name + "Id";

        var allProps = new List<PropertyInfo>();

        foreach (PropertyInfo p in t.GetProperties()) {
            if (p.PropertyType.IsGenericType) {
                dynamic GenericTypeDefinition = p.PropertyType.GetGenericTypeDefinition();
                if (GenericTypeDefinition == typeof(ObservableCollection<>) || GenericTypeDefinition == typeof(ICollection<>) || GenericTypeDefinition == typeof(IEnumerable<>)) {
                    allProps.Add(p);
                }
            }
        }

        foreach (PropertyInfo prop in allProps) {
            // This checks if the other type has a FK Property of this Type.
            var type = prop.PropertyType.GetGenericArguments().First();

            bool HasOneProperty = type.GetProperties().Any(x => x.Name.Equals(fkName, StringComparison.OrdinalIgnoreCase));

            if (HasOneProperty) {
                navigationProperties.Add(prop);
            }

        }

        return navigationProperties;

    }
Run Code Online (Sandbox Code Playgroud)