3

我有一个扩展方法,它执行以下操作:

public static bool Between(this DateTime target, DateTime startDate, DateTime endDate)
{
    return target >= startDate && target <= endDate;
}

我可以这样称呼它

if (expectedDate.Between(minDate, maxDate)) { do code }

我现在正在尝试在 Linq/Lambda 表达式中使用它,例如

    return list.Where(item => targetDate.Between(item.StartDate, item.EndDate));
OR  if (!list.Any(pp => targetDate.Between(pp.StartDate, pp.EndDate)))

我在运行时收到以下错误:

LINQ to Entities 无法识别“Boolean Between(System.DateTime, System.DateTime, System.DateTime)”方法,并且此方法无法转换为存储表达式。

但这很好

if (!list.Any(item => targetDate >= item.StartDate && quoteDate.EventDate <=item.EndDate)))

我想有一个通用的方法来调用。我有哪些选择?

4

3 回答 3

4

不需要的 Brian 解决方案的简单修改AsExpandable()

public static IQueryable<TSource> Between<TSource, TKey>(
    this IQueryable<TSource> source, TKey key,
    Expression<Func<TSource, TKey>> lowSelector,
    Expression<Func<TSource, TKey>> highSelector)
    where TKey : IComparable<TKey>
{
    Expression low = lowSelector.Body;
    Expression high = highSelector.Body;

    Expression lowerBound = Expression.LessThanOrEqual(
        low, Expression.Constant(key));
    Expression upperBound = Expression.LessThanOrEqual(
        Expression.Constant(key), high);

    var lowLambda = Expression.Lambda<Func<TSource, bool>>(
        lowerBound, lowSelector.Parameters);
    var highLambda = Expression.Lambda<Func<TSource, bool>>(
        upperBound, highSelector.Parameters);

    return source.Where(lowLambda).Where(highLambda);
}
于 2011-11-18T10:20:00.600 回答
3

由于您没有使用 LINQ to Object,因此不会执行查询,而是将其转换为要转换为 SQL的表达式树。
LINQ to Entities 不知道如何将您编写的方法转换为 SQL,因为您实现了它。
我从未使用过 LINQ to Entities,但必须有一种方法来扩展表达式树构建器,以使 LINQ to Entities 能够将您的方法转换为 SQL,LINQ to NHibernate 有办法做到这一点。
下面是如何扩展 LINQ to Entities 提供程序的示例。

于 2011-11-16T22:43:13.877 回答
1

我使用几种不同的方法让它工作。在运算符之间构建LINQ我创建了一个新方法

public static IQueryable<TSource> Between<TSource, TKey>(this IQueryable<TSource> source, TKey key, Expression<Func<TSource, TKey>> lowSelector, Expression<Func<TSource, TKey>> highSelector)
    where TKey : IComparable<TKey>
{
    Expression low = Expression.Invoke(lowSelector, lowSelector.Parameters.ToArray());
    Expression high = Expression.Invoke(highSelector, highSelector.Parameters.ToArray());

    Expression lowerBound = Expression.LessThanOrEqual(low, Expression.Constant(key));
    Expression upperBound = Expression.LessThanOrEqual(Expression.Constant(key),  high);

    Expression<Func<TSource, bool>> lambda = Expression.Lambda<Func<TSource, bool>>(lowerBound, lowSelector.Parameters);
    Expression<Func<TSource, bool>> lambda2 = Expression.Lambda<Func<TSource, bool>>(upperBound, highSelector.Parameters);
    return source.AsExpandable().Where(lambda).Where(lambda2);
}

除非我使用 AsExpandable 或 ToList(),否则这不起作用。

AsExpandable() 来自LinkKit

ToList() 强制它从 Linq 到实体到 Linq To Objects,但执行 SQL。

感谢您的帮助和建议

于 2011-11-17T18:24:57.583 回答