Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
LINQ表达式和常用方法的扩展方法转换_Linq_Datetime_C# 4.0_Linq To Entities_Linq Expressions - Fatal编程技术网

LINQ表达式和常用方法的扩展方法转换

LINQ表达式和常用方法的扩展方法转换,linq,datetime,c#-4.0,linq-to-entities,linq-expressions,Linq,Datetime,C# 4.0,Linq To Entities,Linq Expressions,我有一个扩展方法,可以执行以下操作: public static bool Between(this DateTime target, DateTime startDate, DateTime endDate) { return target >= startDate && target <= endDate; } 我现在尝试在Linq/Lambda表达式中使用它,比如 return list.Where(item => targetDate.

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

public static bool Between(this DateTime target, DateTime startDate, DateTime endDate)
{
    return target >= startDate && target <= endDate;
}
我现在尝试在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实体无法识别方法“布尔” 在(System.DateTime,System.DateTime,System.DateTime)方法之间, 并且此方法无法转换为存储表达式

但这很好

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

if(!list.Any)(item=>targetDate>=item.StartDate&"eDate.EventDate因为您没有使用LINQ对象,所以查询没有被执行,而是被转换为要转换为SQL的对象。
LINQ to Entities不知道如何将您编写的方法转换为SQL,因为您实现了它。
我从未使用过LINQ to Entities,但必须有一种方法来扩展表达式树生成器,以使LINQ to Entities能够将您的方法转换为SQL,LINQ to NHibernate有一种方法可以做到这一点。

是一个如何将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);
}
public static IQueryable-Between(此IQueryable源、TKey键、表达式低选择器、表达式高选择器)
其中TKey:i可比较
{
Expression low=Expression.Invoke(lowSelector,lowSelector.Parameters.ToArray());
Expression high=Expression.Invoke(highSelector,highSelector.Parameters.ToArray());
表达式lowerBound=Expression.LessThanOrEqual(低,表达式常数(键));
表达式上限=表达式.lessthanRequal(表达式.常量(键),高);
表达式lambda=Expression.lambda(lowerBound,lowSelector.Parameters);
表达式lambda2=表达式.Lambda(上限,highSelector.Parameters);
返回source.AsExpandable().Where(lambda).Where(lambda2);
}
除非我使用了expandable或ToList(),否则这不起作用

AsExpandable()来自

ToList()强制它从Linq to实体到Linq to对象,但执行SQL


感谢您的帮助和建议

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

公共静态IQueryable在(
此IQueryable源TKey,
表达式低选择器,
表达式(高级选择器)
其中TKey:i可比较
{
表达式low=lowSelector.Body;
表达式high=highSelector.Body;
表达式lowerBound=Expression.lessthanRequal(
低,表达式。常量(键));
表达式上限=Expression.lessthanRequal(
表达式。常数(键),高);
var lowLambda=表达式.Lambda(
lowerBound、lowSelector.Parameters);
var highLambda=表达式.Lambda(
上限,highSelector.Parameters);
返回源.Where(低lambda).Where(高lambda);
}

是否可以这样做:list.Where(item=>targetDate.Between(item.StartDate,item.EndDate))?我需要让它返回表达式、Func、谓词吗?@Brian:你需要将LINQ的抽象语法树解析器扩展到实体。这是可能的,但一些microsoft产品的设计过于粗心。你应该问问实际使用LINQ的人。这是我在google上找到的第一个例子,但考虑到这一事实你实际上不知道LINQ在幕后是如何工作的,如果不了解抽象语法树是什么以及它在.NET Framework中是如何实现的,我怀疑你会成功。这很接近。我正在尝试获取一个目标日期已知的列表,并且开始和结束是列表的属性item@Brian:这可能不会不过要转换为SQL BEVER语句。请检查转换后的SQL,看看它是否真的转换为BEVER语句。
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);
}
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);
}