簡體   English   中英

按nullable排序后,實體框架的導航屬性為null

[英]Entity Framework's navigation properties are null after sort by nullable

我使用以下代碼按表達式轉換順序,因此可空列也可以按順序進行排序。

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;
}

該代碼對於所有非導航屬性都非常適用,但是似乎不再需要查詢導航屬性了。 我使用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,
            }
        }
}

如果我沒有要訂購的東西,那么將加載導航屬性。 但是,一旦有什么要訂購的,導航屬性為null。 如果我跳過三元操作並直接轉到ResourceType.Name屬性,則會收到一個異常,告訴我lambda_method引發了NullReference異常。

我知道訂購導航屬性無法正常工作,但這不是問題。 按“常規”屬性排序會導致此問題。

有什么想法嗎?

事實證明,這個問題並不像我想的那么復雜。 問題是我創建了錯誤的表達式樹。 您可以嵌套表達式,以便導航到屬性的屬性。

以下解決方案應對此進行解釋(這不是我實際解決此問題的方式,但應明確說明):

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;

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM