OrderBy(Func<;T,ICompable>;)可以';不能转换为SQL

本文关键字:不能 可以 转换 SQL ICompable Func lt OrderBy gt | 更新日期: 2023-09-27 18:27:56

我实现了一个动态排序逻辑(请参阅此处),将Expression<Func<T, IComperable>>提供给OrderBy方法。

现在我有一个问题,EF无法将Func<T, IComperable>中的IComperable转换为其实际类型:

无法将类型"System.Int32"强制转换为类型"System.IComparable"。LINQ to Entities仅支持强制转换EDM基元或枚举类型。

System.Data.EEntity.Core.Objects.ELinq.ExpressionConverter.ValidateAndAdjustCastTypes(TypeUsagetoType,TypeUsagefromType,TypetoClrType,TypefromClrType)

有办法解决这个问题吗

目前我发现的唯一方法是将Func<>"实现"为它们的真实类型,将此类型保存在Func<>旁边,并通过反射调用OrderBy

public static IQueryable<T> OrderBy<T>(this IQueryable<T> source, Type orderType, object expression)
{
    return typeof(Queryable).GetMethods().First(m => m.Name == "OrderBy")
       .MakeGenericMethod(typeof(T), orderType)
       .Invoke(null, new object[] { source, expression }) as IQueryable<T>
}

但对我来说,这似乎很丑陋(而且很慢。。。

更新:
这个问题似乎只在Func<T, IComperable>中返回intbool时发生,因为它与string配合良好。。。

OrderBy(Func<;T,ICompable>;)可以';不能转换为SQL

我现在用以下方式解决了它:

var orderDelegates = new Dictionary<string, LambdaExpression>();
Expression<Func<Image, int>> id = i => i.Id;
orderDelegates.Add(ContentItem.ORDER_BY_ID, id);
Expression<Func<Image, IComperable>> title = i => i.Title;
orderDelegates.Add(ContentItem.ORDER_BY_Title, title);
//more items...

(我希望这个短一点-见这里)

在我自己的OrderBy:中

var first = orderDelegates[orderKey ?? defaultKey];
Type firstType = first.GetType().GetGenericArguments()[0].GetGenericArguments()[1];
IOrderedQueryable<T> firstOrder;
if (firstType == typeof(int))
    firstOrder = items.OrderBy<T, int>(first, direction);
else if (firstType == typeof(bool))
    firstOrder = items.OrderBy<T, bool>(first, direction);
else
    firstOrder = items.OrderBy<T, IComparable>(first, direction);
var second = orderDelegates[defaultKey];
Type secondType = second.GetType().GetGenericArguments()[0].GetGenericArguments()[1];
if (secondType == typeof(int))
    return firstOrder.ThenBy<T, int>(second, direction);
else if (secondType == typeof(bool))
    return firstOrder.ThenBy<T, bool>(second, direction);
else
    return firstOrder.ThenBy<T, IComparable>(second, direction);

public static IOrderedQueryable<T> OrderBy<T, K>(this IQueryable<T> items, LambdaExpression expression, OrderDirection? direction)
{
    if (direction == OrderDirection.Ascending || !direction.HasValue)
        return items.OrderBy(expression as Expression<Func<T, K>>);
    else
        return items.OrderByDescending(expression as Expression<Func<T, K>>);
}
public static IQueryable<T> ThenBy<T, K>(this IOrderedQueryable<T> items, LambdaExpression expression, OrderDirection? direction)
{
    if (direction == OrderDirection.Ascending || !direction.HasValue)
        return items.ThenBy(expression as Expression<Func<T, K>>);
    else
        return items.ThenByDescending(expression as Expression<Func<T, K>>);
}
相关文章: