Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/258.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 实体框架&x27;的导航属性在按nullable排序后为null_C#_Entity Framework_Sorting_Lambda_Expression - Fatal编程技术网

C# 实体框架&x27;的导航属性在按nullable排序后为null

C# 实体框架&x27;的导航属性在按nullable排序后为null,c#,entity-framework,sorting,lambda,expression,C#,Entity Framework,Sorting,Lambda,Expression,我使用下面的代码来转换order by表达式,以便也可以对可为空的列进行排序 protected virtual Expression<Func<T, object>> GetSorting(string ordering) { Expression<Func<T, object>> expression = default(Expression<Func<T, object>>); IEnu

我使用下面的代码来转换order by表达式,以便也可以对可为空的列进行排序

protected virtual Expression<Func<T, object>> GetSorting(string ordering)
{
        Expression<Func<T, object>> expression = default(Expression<Func<T, object>>);
        IEnumerable<Order> sortObjects = string.IsNullOrEmpty(ordering) ? null : JsonConvert.DeserializeObject<IEnumerable<Order>>(ordering);
        if (sortObjects != null)
        {
            foreach (Order sortObject in sortObjects)
            {
                Expression<Func<T, object>> currentExpression = this.GetExpression(sortObject.Property);
                expression = this.CombineExpressions(expression, currentExpression);
            }
        }

        return expression;
}

private Expression<Func<T, object>> GetExpression(string propertyName)
{
        Type type = typeof(T);
        ParameterExpression parameter = Expression.Parameter(type, "x");
        MemberExpression propertyReference = Expression.Property(parameter, propertyName);
        Expression conversion = Expression.Convert(propertyReference, typeof(object));
        Expression<Func<T, object>> currentExpression = Expression.Lambda<Func<T, object>>(conversion, new[] { parameter });
        return currentExpression;

}

private Expression<Func<T, object>> CombineExpressions(Expression<Func<T, object>> expression, Expression<Func<T, object>> currentExpression)
{
        if (expression == default(Expression<Func<T, object>>))
        {
            expression = currentExpression;
        }
        else
        {
            // Combine the two expressions' body together
            BinaryExpression body = Expression.AndAlso(expression.Body, currentExpression.Body);
            ParameterExpression[] parameters = new ParameterExpression[1] { Expression.Parameter(typeof(T), expression.Parameters.First().Name) };

            // Convert the BinaryExpression to the requested type
            Expression<Func<T, object>> lambda = Expression.Lambda<Func<T, object>>(body, parameters);

            expression = lambda;
        }

        return expression;
}
受保护的虚拟表达式GetSorting(字符串排序)
{
表达式=默认值(表达式);
IEnumerable sortObjects=string.IsNullOrEmpty(排序)?null:JsonConvert.DeserializeObject(排序);
if(排序对象!=null)
{
foreach(订单sortObject in sortObject)
{
表达式currentExpression=this.GetExpression(sortObject.Property);
expression=this.CombineExpressions(expression,currentExpression);
}
}
返回表达式;
}
私有表达式GetExpression(字符串属性名称)
{
类型=类型(T);
ParameterExpression参数=表达式参数(类型为“x”);
MemberExpression propertyReference=Expression.Property(参数,propertyName);
表达式转换=Expression.Convert(propertyReference,typeof(object));
表达式currentExpression=Expression.Lambda(转换,新[]{parameter});
返回电流表达式;
}
专用表达式组合表达式(表达式表达式,表达式currentExpression)
{
if(表达式==默认值(表达式))
{
表达式=当前表达式;
}
其他的
{
//将两个表达式的主体组合在一起
BinaryExpression body=Expression.AndAlso(Expression.body,currentExpression.body);
ParameterExpression[]parameters=新的ParameterExpression[1]{Expression.Parameter(typeof(T),Expression.parameters.First().Name)};
//将BinaryExpression转换为请求的类型
表达式lambda=表达式.lambda(主体,参数);
表达式=λ;
}
返回表达式;
}
此代码适用于所有非导航属性,但似乎不再查询导航属性。我使用Select表达式加载导航属性,如下所示:

protected override Expression<Func<Resource, ResourceViewModel>> Selector
{
        get
        {
            return (x) => new ResourceViewModel()
            {
                ResourceId = x.ResourceId,
                DisplayName = x.DisplayName,                  
                ResourceType = x.ResourceType != null ? x.ResourceType.Name : string.Empty,
            }
        }
}
受保护的重写表达式选择器
{
得到
{
return(x)=>newResourceViewModel()
{
ResourceId=x.ResourceId,
DisplayName=x.DisplayName,
ResourceType=x.ResourceType!=null?x.ResourceType.Name:string.Empty,
}
}
}
如果我没有任何订购依据,则会加载导航属性。但只要有任何东西需要订购,导航属性就为空。如果我跳过三元操作,直接转到ResourceType.Name属性,我会得到一个异常,告诉我lambda_方法抛出了一个NullReference异常

我知道订购导航属性本身不起作用,但这不是问题所在。按“常规”属性排序会导致此问题


对此有什么想法吗?

原来问题并不像我想的那么复杂。问题是我创建了错误的表达式树。可以嵌套表达式,以便导航到属性的属性

下面的解决方案应该可以解释这一点(这不是我实际解决问题的方式,但应该清楚):

私有表达式GetExpression(字符串父类,字符串属性名称)
{
类型=类型(T);
ParameterExpression参数=表达式参数(类型为“x”);
//获取父类表达式
//将导致(x)=>x.myNavigationPropertyHisaClass
MemberExpression propertyReference1=Expression.Property(参数,父类);
//导航到导航属性类的属性
//将导致(x)=>x.MyNavigationPropertyHichisaClass.MyPropertyIWantToSort
MemberExpression propertyReference2=Expression.Property(PropertyReference1,propertyName);
表达式转换=Expression.Convert(propertyReference2,typeof(object));
表达式currentExpression=Expression.Lambda(转换,新[]{parameter});
返回电流表达式;
}

让我们从这里开始。Order by表达式不能像谓词一样组合,但需要与
OrderBy/ThenBy
链接。这意味着您需要一种不同的方法-
IQueryable
扩展方法,而不是表达式返回方法。在应用order by表达式时,不需要将它们转换为类型
object
。我同意您的第一句话,但您的第二种方法似乎不正确。您需要为订购定义TKey类型。因为我的场景必须能够接受任何类型,所以我只使用了object。但这两种说法都与我的问题无关。我已经为这个问题创建了一个解决方案,但我仍然很好奇这是否可能。问题是,
表达式
表达式不同(不能转换为)
表达式
。另外,当您使用类似这样的
Expression>e=x=>x.IntProperty
时,生成的表达式体不是从上面可以预期的成员访问,而是
Convert
。如果很容易忽略,
OrderBy/ThenBy
为什么要声明第二个泛型参数呢?这是有道理的,但是排序确实是这样工作的,特别是因为我想进行转换(因为可以为null的属性)。但也许这就是为什么导航属性不再包含在流程中的原因?如果您提供一个小而完整的示例,会更容易。当您手动构建查询时,它被转换为SQL,在该上下文中不需要特殊的
null
处理,因为数据库自然地支持
null
(在
orderby
select
等中),并且在该上下文中没有真正的导航属性“load”。如果您从sele获得NRE
private Expression<Func<T, object>> GetExpression(string parentClass, string propertyName)
{
    Type type = typeof(T);
    ParameterExpression parameter = Expression.Parameter(type, "x");

    // Get parent class expression
    // Will result in (x) => x.MyNavigationPropertyWhichIsAClass
    MemberExpression propertyReference1 = Expression.Property(parameter, parentclass);

    // Navigate to the property of the navigation property class
    // Will result in (x) => x.MyNavigationPropertyWhichIsAClass.MyPropertyIWantToSort
    MemberExpression propertyReference2 = Expression.Property(propertyRefernce1, propertyName);

    Expression conversion = Expression.Convert(propertyReference2, typeof(object));
    Expression<Func<T, object>> currentExpression = Expression.Lambda<Func<T, object>>(conversion, new[] { parameter });
    return currentExpression;

}