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