簡體   English   中英

LINQ to Entities OrderBy表達式樹

[英]LINQ to Entities OrderBy Expression Tree

我正在嘗試編寫一個LINQ查詢來orderBy由字符串值給出的動態屬性。

這是我的原始代碼:

 Expression<Func<T, dynamic>> orderBy = i => i.GetType().GetProperty("PropertyName").GetValue(null);

當我試圖運行此命令時,我得到以下異常:

LINQ to Entities無法識別方法'System.Object GetValue(System.Object)'方法,並且此方法無法轉換為存儲表達式。

我試圖通過創建一個表達樹來解決這個問題,該表達式將給出相同的結果。 代碼應該能夠返回任何類型,具體取決於參數,但我遇到了返回類型的問題。 如果我沒有轉換值,我會得到一個不同的錯誤,說無法將Nullable DateTime轉換為Object。 這是我到目前為止的代碼:

ParameterExpression pe = Expression.Parameter(typeof(T), "s");
Expression<Func<T, dynamic>> orderByExpression = Expression.Lambda<Func<T, dynamic>>(Expression.Convert(Expression.Property(pe, "PropertyName"), typeof(object)), pe);

和我的新例外:

無法將類型'System.Nullable`1 [[System.DateTime]]'強制轉換為'System.Object'類型。 LINQ to Entities僅支持轉換EDM原語或枚舉類型。

如何編寫此表達式樹以返回動態類型? 還有一種更好的方法我應該在LINQ中這樣做嗎?

Expression<Func<T, TT>>沒有模板參數,它允許您表示引用類型和值類型。 當然,您可以構建表達式,但必須通過反射與它們進行交互。

這將正確排序集合:

IOrderedEnumerable<TEntityType> SortMeDynamically<TEntityType>(IEnumerable<TEntityType> query, string propertyname)
{
    var param = Expression.Parameter(typeof(TEntityType), "s");
    var prop = Expression.PropertyOrField(param, propertyname);
    var sortLambda = Expression.Lambda(prop, param);

    Expression<Func<IOrderedEnumerable<TEntityType>>> sortMethod = (() => query.OrderBy<TEntityType, object>(k => null));

    var methodCallExpression = (sortMethod.Body as MethodCallExpression);
    if (methodCallExpression == null)
        throw new Exception("Oops");

    var method = methodCallExpression.Method.GetGenericMethodDefinition();
    var genericSortMethod = method.MakeGenericMethod(typeof(TEntityType), prop.Type);
    var orderedQuery = (IOrderedEnumerable<TEntityType>)genericSortMethod.Invoke(query, new object[] { query, sortLambda.Compile() });

    return orderedQuery;
}

或者,如果你想在IQueryable上使用它(例如,如果你使用的是EF)

IOrderedQueryable<TEntityType> SortMeDynamically<TEntityType>(IQueryable<TEntityType> query, string propertyname)
{
    var param = Expression.Parameter(typeof(TEntityType), "s");
    var prop = Expression.PropertyOrField(param, propertyname);
    var sortLambda = Expression.Lambda(prop, param);

    Expression<Func<IOrderedQueryable<TEntityType>>> sortMethod = (() => query.OrderBy<TEntityType, object>(k => null));

    var methodCallExpression = (sortMethod.Body as MethodCallExpression);
    if (methodCallExpression == null)
        throw new Exception("Oops");

    var method = methodCallExpression.Method.GetGenericMethodDefinition();
    var genericSortMethod = method.MakeGenericMethod(typeof(TEntityType), prop.Type);
    var orderedQuery = (IOrderedQueryable<TEntityType>)genericSortMethod.Invoke(query, new object[] { query, sortLambda });

    return orderedQuery;
}

暫無
暫無

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

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