Linq,Expressions,NHibernate和Like比较

我试图做一个基于外部参数(通过搜索表单传递)的比较来确定比较类型( "%string""string%""%string%"

我正朝着以下方向思考:

 query = query.Where( Entity.StringProperty.Like("SearchString", SelectedComparsionType) ) 

类似方法将比基于所选类型返回.StartsWith().EndsWith().SubString()

我对表达式的了解显然远远不够,因为我无法构造一个可以产生正确结果的方法(SQL中的服务器端比较与StartsWith方法一样)。

简单的方法

只是用

 if (comparison == ComparisonType.StartsWith) query = query.Where(e => e.StringProperty.StartsWith("SearchString")); else if ... 

艰难的方式

如果你想做这样的事情,要么确保你的LINQ提供程序能以某种方式被告知这个新方法,以及它如何转换为SQL(不太可能),或者阻止你的方法到达LINQ提供者,并为提供者提供一些东西它理解(很难)。 例如,而不是

 query.Where(e => CompMethod(e.StringProperty, "SearchString", comparsionType)) 

你可以创造类似的东西

 var query = source.WhereLike(e => e.StringProperty, "SearchString", comparsionType) 

使用以下代码

 public enum ComparisonType { StartsWith, EndsWith, Contains } public static class QueryableExtensions { public static IQueryable WhereLike( this IQueryable source, Expression> field, string value, SelectedComparisonType comparisonType) { ParameterExpression p = field.Parameters[0]; return source.Where( Expression.Lambda>( Expression.Call( field.Body, comparisonType.ToString(), null, Expression.Constant(value)), p)); } } 

您甚至可以通过这种方式添加其他条件

 var query = from e in source.WhereLike( e => e.StringProperty, "SearchString", comparsionType) where e.OtherProperty == 123 orderby e.StringProperty select e; 

非常非常困难的方式

(技术上)可以在提供者看到之前重写表达式树,因此您可以首先使用您想到的查询,但是您必须

  • 创建一个Where(this IQueryable source, Expression> predicate)来拦截Queryable.Where
  • 重写表达式树,用其中一个String方法替换你的CompMethod ,无论它在哪里,
  • 使用重写的表达式调用原始的Queryable.Where
  • 首先,能够首先遵循上面的扩展方法!

但这对你的想法来说可能太复杂了。

听起来你应该想要使用:

 query = query.Where( Entity.StringProperty.Contains("SearchString") ) 

这应该映射到:

 WHERE StringProperty LIKE '%SearchString%' 

这也适用于更高级的搜索掩码,例如“Mr?Sm%th”,但我还没有必须测试任何类似的搜索字符串。


更新:基于OPs编辑

这听起来像你要求的是如下:

  public enum SelectedComparsionType { StartsWith, EndsWith, Contains } public static bool Like(this string searchString, string searchPattern, SelectedComparsionType searchType) { switch (searchType) { case SelectedComparsionType.StartsWith: return searchString.StartsWith(searchPattern); case SelectedComparsionType.EndsWith: return searchString.EndsWith(searchPattern); case SelectedComparsionType.Contains: default: return searchString.Contains(searchPattern); } } 

这将允许您根据需要编写代码,即:

 query = query.Where( Entity.StringProperty.Like("SearchString", SelectedComparsionType.StartsWith) ) 

但是,就个人而言 ,我会直接调用所需的字符串函数来替换SelectedComparsionType的任何使用。 即

 query = query.Where( Entity.StringProperty.StartsWith("SearchString") ) 

因为它仍将映射到SQL’LIKE’查询。

这正是我的想法,谢谢。 我已经编写了类似的东西,但它没有转换为SQL。 例如,如果我直接这样做,它会起作用:

 Entity.StringProperty.EndsWith("SearchString"); 

如果我使用专用方法,它不起作用:

 CompMethod("BaseString","SearchString",SelectedComparsionType.EndsWith) 

我认为它可能与表达式评估有关,我只是不确定是什么。

您最好使用Regex来解决此问题。