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来解决此问题。