Linq,Expressions,NHibernate和Like比较

时间:2009-08-04 09:49:26

标签: c# linq nhibernate

我正在尝试基于外部参数(通过搜索表单传递)进行比较,以确定比较类型("%string""string%""%string%"

我正朝着以下方向思考:

query = query.Where(
    Entity.StringProperty.Like("SearchString", SelectedComparsionType)
)

类似方法会比基于所选类型返回 .StartsWith().EndsWith().SubString()

我对表达式的了解显然远非如此,因为我无法构造一个可以产生正确结果的方法(SQL中的服务器端比较与StartsWith方法一样)。

4 个答案:

答案 0 :(得分:17)

简单方法

只需使用

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<T> WhereLike<T>(
        this IQueryable<T> source,
        Expression<Func<T, string>> field, 
        string value,
        SelectedComparisonType comparisonType)
    {
        ParameterExpression p = field.Parameters[0];
        return source.Where(
            Expression.Lambda<Func<T, bool>>(
                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;

非常非常困难的方式

在技术上可以在提供者看到之前重写表达式树,因此可以首先使用您想到的查询,但是您必须< / p>

  • 创建Where(this IQueryable<EntityType> source, Expression<Func<EntityType, bool>> predicate)以拦截Queryable.Where
  • 使用其中一种CompMethod方法重写表达式树,将String替换为Queryable.Where
  • 使用重写的表达式
  • 调用原始{{1}}
  • 首先,能够首先遵循上面的扩展方法!

但对于你的想法,这可能太复杂了。

答案 1 :(得分:1)

听起来你应该想要使用:

query = query.Where(
Entity.StringProperty.Contains("SearchString")
)

这应该映射到:

WHERE StringProperty LIKE '%SearchString%'

这也应该适用于更高级的搜索掩码,例如“Mr?Sm%th”,但我还没有像我一样测试任何搜索字符串。


更新:基于OP编辑

听起来你要求的是以下内容:

   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'查询。

答案 2 :(得分:0)

这正是我的想法,谢谢。我已经编写了类似的东西,但它没有转换为SQL。例如,如果我直接这样做,它就起作用了:

Entity.StringProperty.EndsWith("SearchString");

如果我使用专用方法,它无效:

CompMethod("BaseString","SearchString",SelectedComparsionType.EndsWith)

我认为它可能与表达式评估有关,我只是不确定是什么。

答案 3 :(得分:-1)

最好使用Regex来解决此问题。