Linq,Expressions,NHibernate和Like比较

6 c# linq nhibernate

我试图做一个基于外部参数(通过搜索表单传递)的比较来确定比较类型("%string""string%""%string%")

我正朝着以下方向思考:

query = query.Where(
    Entity.StringProperty.Like("SearchString", SelectedComparsionType)
)
Run Code Online (Sandbox Code Playgroud)

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

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

Rub*_*ben 17

简单的方法

只是用

if (comparison == ComparisonType.StartsWith)
    query = query.Where(e => e.StringProperty.StartsWith("SearchString"));
else if ...
Run Code Online (Sandbox Code Playgroud)

艰难的方式

如果你想做这样的事情,要么确保你的LINQ提供程序能以某种方式被告知这个新方法,以及它如何转换为SQL(不太可能),或者阻止你的方法到达LINQ提供者,并为提供者提供一些东西它理解(很难).例如,而不是

query.Where(e => CompMethod(e.StringProperty, "SearchString", comparsionType))
Run Code Online (Sandbox Code Playgroud)

你可以创造类似的东西

var query = source.WhereLike(e => e.StringProperty, "SearchString", comparsionType)
Run Code Online (Sandbox Code Playgroud)

使用以下代码

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));
    }
}
Run Code Online (Sandbox Code Playgroud)

您甚至可以通过这种方式添加其他条件

var query = from e in source.WhereLike(
                e => e.StringProperty, "SearchString", comparsionType)
            where e.OtherProperty == 123
            orderby e.StringProperty
            select e;
Run Code Online (Sandbox Code Playgroud)

非常非常努力的方式

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

  • 创建一个Where(this IQueryable<EntityType> source, Expression<Func<EntityType, bool>> predicate)拦截Queryable.Where,
  • 重写表达式树,用CompMethod其中一种String方法替换你的,无论它在哪里,
  • Queryable.Where用重写的表达式调用原文,
  • 首先,能够首先遵循上面的扩展方法!

但这对你想到的东西来说可能太复杂了.