2

重複の可能性:
動的LINQ OrderBy

私はEntityFrameworkを使用しており、。などの並べ替えを行うための文字列を入力できる独自の動的並べ替えメソッドを作成したいと思いますquery.DynamicSort("Name, Age DESC")

MSがいくつかの動的なlinqコードを出力したことは知っていますが、それは私が必要とする以上のものであり、ソートのためだけにその簡略化されたバージョンを自分で作成する方法を理解しようとしています。

単一のフィールドで機能するように運が良かったのですが、複数のフィールドで並べ替えようとすると、次のエラーが発生します。

パラメーター'x'は、指定されたLINQtoEntitiesクエリ式にバインドされていませんでした。

これが私のコードです。誰かが私がどこで間違っているのかを見て、おそらくいくつかの修正を提案できますか?式を動的に作成するのが苦手です。

public static class DynamicQuery
{
    private class SortField
    {
        public Expression Expression;
        public bool       Descending = false;
        public Type       Type;
    }

    public static IOrderedQueryable<T> DynamicSort<T>(this IQueryable<T> source, string sortOrder)
    {
        var fields     = sortOrder.Split(',');
        var sortFields = new List<SortField>();

        ParameterExpression arg = null;

        for (int i = 0; i < fields.Length; i++)
        {
            var sf = new SortField();
            sortFields.Add(sf);

            //Handle Descending Sort Fields
            if (fields[i].EndsWith(" DESC", StringComparison.OrdinalIgnoreCase))
            {
                sf.Descending = true;
                fields[i] = fields[i].Substring(0, (fields[i].Length - 5));  //Remove " DESC"
            }

            fields[i] = fields[i].Trim();

            //Handle fields that have nested properties
            var props = fields[i].Split('.');
            sf.Type = typeof(T);
            sf.Expression = arg = Expression.Parameter(sf.Type, "x");  //Create an x parameter of type T

            foreach (string prop in props)
            {
                PropertyInfo pi = sf.Type.GetProperty(prop);
                sf.Expression = Expression.Property(sf.Expression, pi);
                sf.Type = pi.PropertyType;
            }
        }

        //Now that we have the SortFields we can do the sorting
        Expression queryExpr = source.Expression;
        string methodAsc = "OrderBy";
        string methodDesc = "OrderByDescending";
        foreach (var sf in sortFields)
        {
            LambdaExpression lambda = Expression.Lambda(sf.Expression, arg);

            queryExpr = Expression.Call(
                typeof(Queryable), sf.Descending ? methodDesc : methodAsc,
                new Type[] { source.ElementType, sf.Type },
                queryExpr, Expression.Quote(lambda));
            methodAsc = "ThenBy";
            methodDesc = "ThenByDescending";
        }
        return (IOrderedQueryable<T>)source.Provider.CreateQuery(queryExpr);
    }
}

どうもありがとう。

4

0 に答える 0