linq to Entities中where子句中的扩展方法

在linq to Entities中,我们需要一个类似“sql like”的方法。 我们已经为IQueryable实现了我们自己的扩展方法,因为包含的方法对我们不起作用,因为它不接受像’%a%b%’这样的模式

创建的代码是:

private const char WildcardCharacter = '%'; public static IQueryable WhereLike(this IQueryable _source, Expression<Func> _valueSelector, string _textSearch) { if (_valueSelector == null) { throw new ArgumentNullException("valueSelector"); } return _source.Where(BuildLikeExpressionWithWildcards(_valueSelector, _textSearch)); } private static Expression<Func> BuildLikeExpressionWithWildcards(Expression<Func> _valueSelector, string _textToSearch) { var method = GetPatIndexMethod(); var body = Expression.Call(method, Expression.Constant(WildcardCharacter + _textToSearch + WildcardCharacter), _valueSelector.Body); var parameter = _valueSelector.Parameters.Single(); UnaryExpression expressionConvert = Expression.Convert(Expression.Constant(0), typeof(int?)); return Expression.Lambda<Func> (Expression.GreaterThan(body, expressionConvert), parameter); } private static MethodInfo GetPatIndexMethod() { var methodName = "PatIndex"; Type stringType = typeof(SqlFunctions); return stringType.GetMethod(methodName); } 

这工作正常,代码完全在SqlServer中执行,但现在我们将在where子句中使用此扩展方法:

 myDBContext.MyObject.Where(o => o.Description.Like(patternToSearch) || o.Title.Like(patterToSerch)); 

问题是where子句中使用的方法必须返回bool结果,如果它与’||’之类的运算符一起使用 ,我不知道如何使我创建的代码返回一个bool并保持代码在sqlserver中执行。 我想我必须通过BuildLinqExpression方法将返回的Expression转换为bool,但我不知道该怎么做

总结一下! 首先,可以在Linq to Entities中创建我们自己的扩展方法来执行SqlServer中的代码吗? 如果这是可能的我怎么做呢?

谢谢你的帮助。

不,您无法教育EF处理您的自定义扩展方法,即使您拥有构建可用于EF的表达式的代码。

或者:

  • 直接在EF Where表达式中使用SqlFunctions方法
  • 使用ExpressionVisitor将多个表达式组合成一个复合( OrElse / AndAlso )表达式(注意这不会帮助你拥有你想要的代码,但它会让你使用你的两个方法并对它们执行|| – 它会看起来虽然复杂

第一个更简单,更清晰。

这里回答: https : //stackoverflow.com/a/10726256/84206

他的代码: http : //pastebin.com/4fMjaCMV

允许您将扩展方法标记为[Expandable] ,只要它返回的表达式与linq2entities一起使用,它将用内部表达式替换函数调用。 请注意,内联lambda会产生错误,因此我必须将它们声明为局部变量或静态变量,例如IsCurrent变量:

 static Expression> IsCurrent = (p) => p.Starts <= DateTime.Now; [ExpandableMethod] public static IQueryable AsOf(this IQueryable source) { return source.Where(IsCurrent); }