nhibernate queryover LIKE 与表达式树

发布于 2024-12-27 19:44:47 字数 779 浏览 3 评论 0原文

我希望向我的基本存储库类添加一个方法,该方法允许我使用 LIKE 表达式,但我不太确定如何进行此操作。我想创建一个通用方法,该方法查看传入的表达式树并在传入的字符串值中查找通配符。然后它将相应地生成 QueryOver 语句。

我目前有以下内容:

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

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

理想情况

下,我想告诉以下内容之间的区别:

  • search*
  • *search
  • *search*

因此生成的查询将是:

  • field LIKE 'search%'
  • field LIKE '%search'
  • field LIKE '%search%'

I'm looking to add a method to my base repository class that allows me to use LIKE expressions but I'm not quite sure of how to go about this. I want to create a generic method that looks at the expression tree passed in and looks for wildcard characters in the string values passed in. It would then generate the QueryOver statement accordingly.

I have the following currently:

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

Obviously the hard part is yet to come. I need to look through the expression tree and build the query using QueryOver dynamically. Looking for some pointers on how to proceed with this. Or am I just wasting my time here and should just create individual methods in my repositories that handle the LIKE queries?

Additional Criteria

Ideally I'd like to tell the difference between the following:

  • search*
  • *search
  • *search*

So the query generated would be:

  • field LIKE 'search%'
  • field LIKE '%search'
  • field LIKE '%search%'

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

唔猫 2025-01-03 19:44:47

在 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 中不起作用。

希望有帮助。

There's two ways to write a Like expression in QueryOver.

If you do it off the Where clause:

.Where(Restrictions.Like(Projections.Property<T>(*projected property*), *string value*, MatchMode.Anywhere))

However this is kinda long to write.

So you can use WhereRestrictionOn:

.WhereRestrictionOn(*projected property*).IsLike(*string value*, MatchMode.Anywhere)

This means you need to pass in two parameters like:

FindAll<User>(x => x.FirstName, "bob");

You may be able to use .Contains, .StartsWith, .EndsWith, but I'm not sure.

FindAll<User>(x => x.FirstName.Contains("bob"));
FindAll<User>(x => x.FirstName.StartsWith("bob"));
FindAll<User>(x => x.FirstName.EndsWith("bob"));

I don't think those work in NHibernate.

Hope that helps.

倚栏听风 2025-01-03 19:44:47

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

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

生成一个property 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() 附加您的其他条件。缺点是丢失强类型查询。

I don't really understand what you want to do. Do you want for a query such as

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

to generate a property LIKE "%substring%" query? In most Linq providers the String.Contains method is transformed in a "LIKE" query, and thus you wouldn't need to look for wildcard characters in the expression tree, only for the String.Contains method.
In case of the latter, you would have to parse the expression tree looking for a String.Contains() method. This could be very troublesome (http://msdn.microsoft.com/en-us/library/bb397951.aspx). Also, I can't see in your method which property is to be "compared" with the LIKE operator.

Anyways, I think it would be easier to pass a ICriterion to your .Where(), such as

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

, and append your other conditions with .And() right after that. The drawback is losing strongly-typed queries.

无人问我粥可暖 2025-01-03 19:44:47

在深入研究了将表单表达式转换

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

After digging for a while for a solution about the problem of translating expressions of the form

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

into SQL of the form

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

I came up with the following solution: Yu have to Register custom method calls for the Standard string functions .Contains(), .StartsWith, .EndsWith().
God knows why these functions are not registered by default within NHibernate. The following code should help you out.

/// 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);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文