實體框架:LINQ to Entities僅支持轉換實體數據模型基元類型

entity-framework primitive-types

我編寫了一個方法來允許為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或整數,因為我得到上面的錯誤消息。

到目前為止,我(鬆散地)理解問題是實體框架需要它是主/ EDM類型,因為它必須將C#DateTime轉換為數據庫可以處理的內容。

有沒有辦法將日期時間轉換為基本類型,以便這仍然有效?

通過方法獲取訂單的方法:(接受查詢並以“有序形式”返回)

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();

一般承認的答案

實體框架使這很困難,我不確定是否有辦法用單一返回值類型(IComparable,object等)做你想做的事情。您可以考慮將您的設計重新Func<IQueryable<K>, IOrderedQueryable<K>>為name-to- Func<IQueryable<K>, IOrderedQueryable<K>>值的字典:

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

然後像這樣應用它:

var orderedQuery = query.OrderBy(item => item.DefaultOrderColumn);

Func<IQueryable<K>, IOrderedQueryable<K>> assignOrderBy = null;

if (_possibleSortForForumItem.TryGetValue(orderColumnName, out assignOrderBy))
{
    orderedQuery = assignOrderBy(query);
}

熱門答案

我知道這是舊的,但我希望完成與OP完全相同的事情,並且不想在我的字典中使用Func<IQueryable<T>, IOrderedQueryable<T>> 。主要是因為我必須同時實現OrderByOrderByDescending委託。

我最終為IQueryable創建了一個名為ObjectSort的擴展方法,它只是檢查表達式的返回類型應該是什麼,然後使用該類型創建一個新的lambda,以便LINQ to Entities不會出錯。

我不確定這是否是一個很好的解決方案,但下面的例子確實適用於DateTimeint所以希望它可以給你一些想法,如果你想要完成類似的東西!

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


許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因
許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因