使用表达式树对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%"

使用表达式树对LIKE进行nhibernate查询

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