nhibernate queryover LIKE with expression trees

时间:2012-01-17 00:06:28

标签: c# nhibernate queryover

我想在我的基础知识库类中添加一个方法,允许我使用 LIKE 表达式,但我不太清楚如何解决这个问题。我想创建一个泛型方法,查看传入的表达式树,并在传入的字符串值中查找通配符。然后它会相应地生成QueryOver语句。

我目前有以下内容:

public IList<T> FindAll(Expression<Func<T, bool>> criteria, char wildCard)
{
    return SessionFactory.GetCurrentSession()
            .QueryOver<T>()
            .Where(criteria)
            .List();
}

显然,困难的部分尚未到来。我需要查看表达式树并动态地使用QueryOver构建查询。寻找关于如何继续这一点的一些指示。或者我只是在这里浪费时间,应该在我的存储库中创建处理 LIKE 查询的单个方法?

附加标准

理想情况下,我想区分以下内容:

  • 搜索*
  • *搜索
  • *搜索*

因此生成的查询将是:

  • 字段LIKE'search%'
  • 字段LIKE'%search'
  • 字段LIKE'%search%'

3 个答案:

答案 0 :(得分:13)

在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。

希望有所帮助。

答案 1 :(得分:0)

我真的不明白你想做什么。您想要查询,例如

session.QueryOver<T>().Where(x => x.property == "*substring*").List();

生成属性LIKE“%substring%”查询?在大多数Linq提供程序中,String.Contains方法在“LIKE”查询中进行转换,因此您不需要在表达式树中查找通配符,仅用于String.Contains方法。
如果是后者,则必须解析表达式树以查找String.Contains()方法。这可能非常麻烦(http://msdn.microsoft.com/en-us/library/bb397951.aspx)。另外,我在你的方法中看不到哪个属性与LIKE运算符“比较”。

无论如何,我认为将ICriterion传递给.Where()更容易,例如

.Where(new NHibernate.Criterion.LikeExpression("property", "%value%"))

,然后用.And()追加你的其他条件。缺点是丢失强类型查询。

答案 2 :(得分:-1)

挖掘一段时间后,找出关于翻译表格表达式问题的解决方案

session.QueryOver<T>().Where(x => x.StringAttrbute.StartsWith("ajoofa"))

到表格的SQL

SELECT * FROM {table} WHERE {string_attribute} LIKE 'ajoofa%'

我想出了以下解决方案:Yu必须为标准字符串函数注册自定义方法调用.Contains(),. StartWith,.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);
}