使用表达式树对LIKE进行nhibernate查询
本文关键字:进行 nhibernate 查询 LIKE 表达式 | 更新日期: 2023-09-27 18:20:33
我想在我的基本存储库类中添加一个方法,该方法允许我使用LIKE表达式,但我不太确定如何进行。我想创建一个通用方法,查看传入的表达式树,并在传入的字符串值中查找通配符。然后,它将相应地生成QueryOver
语句。
我目前有以下内容:
public IList<T> FindAll(Expression<Func<T, bool>> criteria, char wildCard)
{
return SessionFactory.GetCurrentSession()
.QueryOver<T>()
.Where(criteria)
.List();
}
显然,困难的部分还没有到来。我需要查看表达式树,并使用QueryOver
动态构建查询。寻找一些关于如何进行这项工作的建议。还是我只是在这里浪费时间,应该在我的存储库中创建单独的方法来处理LIKE查询?
附加标准
理想情况下,我想告诉以下之间的区别:
- 搜索*
- *搜索
- *搜索*
因此生成的查询将是:
- 字段LIKE"搜索%"
- 字段LIKE"%搜索"
- 字段LIKE"%search%"
QueryOver中有两种编写Like表达式的方法。
如果你不使用Where子句:
.Where(Restrictions.Like(Projections.Property<T>(*projected property*), *string value*, MatchMode.Anywhere))
然而,这写起来有点长。
因此,您可以使用WhereRestrictionOn:
.WhereRestrictionOn(*projected property*).IsLike(*string value*, MatchMode.Anywhere)
这意味着您需要传入两个参数,如:
FindAll<User>(x => x.FirstName, "bob");
您可以使用.Contains、.StartsWith、.EndsWith,但我不确定。
FindAll<User>(x => x.FirstName.Contains("bob"));
FindAll<User>(x => x.FirstName.StartsWith("bob"));
FindAll<User>(x => x.FirstName.EndsWith("bob"));
我不认为这些在NHibernate工作。
希望能有所帮助。
我真的不明白你想做什么。你想要像这样的查询吗
session.QueryOver<T>().Where(x => x.property == "*substring*").List();
生成属性LIKE"%substring%"查询?在大多数Linq提供程序中,String.Contains方法是在"LIKE"查询中转换的,因此您不需要在表达式树中查找通配符,只需要查找String.Continus方法
如果是后者,则必须解析表达式树以查找String.Contains()方法。这可能很麻烦(http://msdn.microsoft.com/en-us/library/bb397951.aspx)。此外,在您的方法中,我看不出哪个属性要与LIKE运算符进行"比较"。
无论如何,我认为将ICriteration传递给你的.Where()会更容易,比如
.Where(new NHibernate.Criterion.LikeExpression("property", "%value%"))
,然后在后面添加.and()作为其他条件。缺点是丢失强类型查询。
经过一段时间的挖掘,找到了一个关于翻译形式的表达式的问题的解决方案
session.QueryOver<T>().Where(x => x.StringAttrbute.StartsWith("ajoofa"))
转换为形式的SQL
SELECT * FROM {table} WHERE {string_attribute} LIKE 'ajoofa%'
我想出了以下解决方案:Yu必须为标准字符串函数.Contains()、.StartsWith和.EndsWith()注册自定义方法调用。天知道为什么这些功能默认不在NHibernate中注册。下面的代码应该可以帮助您。
/// Perform the registration of custom methods
/// </summary>
public static void Register()
{
if (!_registered)
{
_registered = true;
String str = null;
ExpressionProcessor.RegisterCustomMethodCall(() => str.StartsWith(null), ProcessStartsWith);
ExpressionProcessor.RegisterCustomMethodCall(() => str.EndsWith(null), ProcessEndsWith);
ExpressionProcessor.RegisterCustomMethodCall(() => str.Contains(null), ProcessContains);
}
}
static ICriterion ProcessStartsWith(MethodCallExpression methodCallExpression)
{
ExpressionProcessor.ProjectionInfo projection = ExpressionProcessor.FindMemberProjection(methodCallExpression.Object);
object value = ExpressionProcessor.FindValue(methodCallExpression.Arguments[0]) + "%";
return projection.CreateCriterion(Restrictions.Like, Restrictions.Like, value);
}
static ICriterion ProcessEndsWith(MethodCallExpression methodCallExpression)
{
ExpressionProcessor.ProjectionInfo projection = ExpressionProcessor.FindMemberProjection(methodCallExpression.Object);
object value = "%" + ExpressionProcessor.FindValue(methodCallExpression.Arguments[0]);
return projection.CreateCriterion(Restrictions.Like, Restrictions.Like, value);
}
static ICriterion ProcessContains(MethodCallExpression methodCallExpression)
{
ExpressionProcessor.ProjectionInfo projection = ExpressionProcessor.FindMemberProjection(methodCallExpression.Object);
object value = "%" + ExpressionProcessor.FindValue(methodCallExpression.Arguments[0]) + "%";
return projection.CreateCriterion(Restrictions.Like, Restrictions.Like, value);
}