Entity Framework: LINQ to Entities は Entity Data Model プリミティブ型のキャストのみをサポートします 質問する

Entity Framework: LINQ to Entities は Entity Data Model プリミティブ型のキャストのみをサポートします 質問する

orderby 句に Expression を渡すことができるメソッドを作成しましたが、この問題が発生しました。

'System.DateTime' 型を 'System.IComparable' 型にキャストできません。LINQ to Entities は、エンティティ データ モデル プリミティブ型のキャストのみをサポートしています。

基本的に表現は次のようになります。

Expression<Func<K, IComparable>> orderBy

そして、次のように使用されます。

SomeEntities.SomeTable
.Where
(
   whereClause
)
.Select
(
   selectClause
)
.OrderBy(orderBy)

そのアイデアは、次のような表現に一致する文字列を辞書に保持できるようにすることです。

_possibleSortForForumItem.Add("CreateDate", item => item.CreateDate);

次に、ソート文字列を受け取り、辞書内のキーと一致する場合は式を返し、一致しない場合はデフォルトを返すメソッドを用意します。(アイデアは、何を基準に並べ替えるかを制御する方法です) これで、これは String プロパティでは機能しますが、これまでのところ、上記のエラー メッセージが表示されるため、datetime または integer では機能しません。

私が(大まかに)理解している限りでは、問題は、Entity Framework が C# DateTime をデータベースが処理できるものに変換する必要があるため、Primary/EDM 型である必要があるということです。

これを引き続き機能させるために、datetime をプリミティブ型に変換する方法はありますか?

解決

order by メソッドを取得する方法: (クエリを受け取り、「順序付けられた形式」で返します)

private static Func<IQueryable<ForumViewItem>, IOrderedQueryable<ForumViewItem>> GetMethodForSort(String sortBy)
{
  if (_methodForSort == null)
  {
    _methodForSort = new Dictionary<String, Func<IQueryable<ForumViewItem>, IOrderedQueryable<ForumViewItem>>>();
    _methodForSort.Add(SortForumViewItemCreatedOn, item => item.OrderBy(innerItem => innerItem.CreatedOn));
    ...
  }

  Func<IQueryable<ForumViewItem>, IOrderedQueryable<ForumViewItem>> orderMethod;

  if(String.IsNullOrEmpty(sortBy) || !_methodForSort.ContainsKey(sortBy))
  {
    orderMethod = _methodForSort["ForumName"];
  }
  else
  {
    orderMethod = _methodForSort[sortBy];
  }

  return orderMethod;
}

汎用クエリ メソッドのメソッド シグネチャ:

IList<K> GetListForGrid<T, K>(this ObjectQuery<T> query, ... Func<IQueryable<K>, IOrderedQueryable<K>> orderBy, ...)

渡されたメソッドの使用法:

initialQuery = query
  .Where
  (
    somethingEqualsSomething
  )
  .Select
  (
    selectClause
  );

var orderedQuery = orderBy(initialQuery);

returnValue = orderedQuery
  .Skip(numberToShow * realPage)
  .Take(numberToShow)
  .ToList();

ベストアンサー1

これは古いことだとはわかっていますが、私は OP とまったく同じことを実現しようとしていたので、辞書で を使用したくありませんでした。主な理由は、とデリゲートのFunc<IQueryable<T>, IOrderedQueryable<T>>両方を実装する必要があるためです。OrderByOrderByDescending

最終的に、IQueryable の拡張メソッドを作成しました。ObjectSortこれは、式の戻り値の型が何であるかを単純にチェックし、その型を使用して新しいラムダを作成するので、LINQ to Entities が異常をきたすことはありません。

これが良い解決策かどうかはわかりませんが、以下の例は機能しますDateTimeので、int同様のことを実現しようとしている場合に、いくつかのアイデアが得られることを願っています。

public static IOrderedQueryable<T> ObjectSort<T>(this IQueryable<T> entities, Expression<Func<T, object>> expression, SortOrder order = SortOrder.Ascending)
{
    var unaryExpression = expression.Body as UnaryExpression;
    if (unaryExpression != null)
    {
        var propertyExpression = (MemberExpression)unaryExpression.Operand;
        var parameters = expression.Parameters;

        if (propertyExpression.Type == typeof(DateTime))
        {
            var newExpression = Expression.Lambda<Func<T, DateTime>>(propertyExpression, parameters);
            return order == SortOrder.Ascending ? entities.OrderBy(newExpression) : entities.OrderByDescending(newExpression);
        }

        if (propertyExpression.Type == typeof(int))
        {
            var newExpression = Expression.Lambda<Func<T, int>>(propertyExpression, parameters);
            return order == SortOrder.Ascending ? entities.OrderBy(newExpression) : entities.OrderByDescending(newExpression);
        }

        throw new NotSupportedException("Object type resolution not implemented for this type");
    }
    return entities.OrderBy(expression);
}

おすすめ記事