5

firstby / thenby次のようにコンボソートを適用できるようにしたい:

allOrders().sort(s => s.ProductName, s => s.OrderDate)

したがって、この投稿をインスピレーションとして使用して、この拡張メソッドを作成しました。これは正常にコンパイルされます。

public static IQueryable<T> sort<T>(this IQueryable<T> entities, params 
  Expression<Func<T, object>>[] predicates) where T : class 
{
  var sorted = entities.OrderBy(predicates[0]);
  for (int i = 1; i < predicates.Length; i++)
    sorted = sorted.ThenBy(predicates[i]);

  return sorted;
}

また、この簡潔なバージョンも試しました。これもコンパイルされます。

public static IQueryable<T> sort<T>(this IQueryable<T> entities, params 
  Expression<Func<T, object>>[] predicates) where T : class
{
  return predicates.Skip(1).Aggregate(
    entities.OrderBy(predicates[0]),
    (aggregate, currentPredicate) => aggregate.ThenBy(currentPredicate));
}

ただし、 a でソートしようとすると、次のDateTime例外が発生します。

タイプ 'System.DateTime' をタイプ 'System.Object' にキャストできません。LINQ to Entities は、EDM プリミティブ型または列挙型のキャストのみをサポートします。

私は何を間違っていますか?EF5を使用しています。

4

2 に答える 2

6

を返すラムダ式から値の型 (intまたは など) を返すと、コンパイラは値の型をボックス化されたオブジェクトに変換する呼び出しを生成します。 DateTimeobjectBox()

Entity Framework 式パーサーは、このボックス式を処理できません。
唯一の解決策は、値の型を返す厳密に型指定されたラムダ式を渡すことです。

そのために、コレクション初期化子を誤用することができます。

public class OrderingCollection<TEntity> : IEnumerable {
    public void Add<TProperty>(Expression<Func<TEntity, TProperty>>) {
        ...
    }
}

public static IQueryable<T> Sort<T>(this IQueryable<T> entities, 
                                    OrderingCollection<T> o) where T : class {
    ...
}


q = q.Sort(new OrderingCollection { s => s.ProductName, s => s.OrderDate });

コレクション初期化子を使用すると、任意の数の異なる型パラメーターで型推論を使用できます。

于 2012-10-24T20:27:09.790 に答える
0

あなたの問題はにあると思いますFunc<T, object>。つまり、並べ替えの対象に関係なくオブジェクトを返すことになり、EF はそれをデータベースの列の型にマップできません。

このOrderBy()関数は aTSourceと a の両方を取るTKeyため、並べ替えごとにキー タイプを指定する必要があり、すぐに制御不能になります (「参考文献」を参照Tuple<T1,T2,T3,T4,T5,T6,T7,T8>)。

于 2012-10-24T20:29:39.650 に答える