OrderBy(Func <t,icomperable =“”>)无法转换为SQL </t,>

时间:2013-08-16 21:31:21

标签: c# sql entity-framework entity-framework-6

我实施了动态排序逻辑(请参阅HERE),为Expression<Func<T, IComperable>>方法提供OrderBy

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

  

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

  

System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.ValidateAndAdjustCastTypes(TypeUsage toType,TypeUsage fromType,Type toClrType,Type fromClrType)

有没有办法解决这个问题?

我目前找到的唯一方法是“实施”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>
}

但这对我来说似乎非常难看(而且速度慢?)并且使用起来并不像现在那样好(很遗憾只能用于LINQ对象工作)解决方案......

更新
这个问题似乎只有在int中返回boolFunc<T, IComperable>时才会出现,因为它适用于string ...

1 个答案:

答案 0 :(得分:1)

我现在以下列方式解决了这个问题:

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...

(我希望这会有点短 - 请参阅HERE

并在我自己的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>>);
}