Linq, Expressions, NHibernate and Like comparison

后端 未结 4 1835
[愿得一人]
[愿得一人] 2021-02-09 18:52

I am trying to do a like comparison based on an outside parameter (passed by a search form) that determines type of comparison (\"%string\" or \"string%\"

4条回答
  •  不要未来只要你来
    2021-02-09 19:27

    The easy way

    Just use

    if (comparison == ComparisonType.StartsWith)
        query = query.Where(e => e.StringProperty.StartsWith("SearchString"));
    else if ...
    

    The hard way

    If you want to do something like this, either make sure your LINQ provider can be told of this new method somehow, and how it translates to SQL (unlikely), or prevent your method from ever reaching the LINQ provider, and provide the provider something it understands (hard). For example, instead of

    query.Where(e => CompMethod(e.StringProperty, "SearchString", comparsionType))
    

    you can create something like

    var query = source.WhereLike(e => e.StringProperty, "SearchString", comparsionType)
    

    with the following code

    public enum ComparisonType { StartsWith, EndsWith, Contains }
    
    public static class QueryableExtensions
    {
        public static IQueryable WhereLike(
            this IQueryable source,
            Expression> field, 
            string value,
            SelectedComparisonType comparisonType)
        {
            ParameterExpression p = field.Parameters[0];
            return source.Where(
                Expression.Lambda>(
                    Expression.Call(
                        field.Body, 
                        comparisonType.ToString(), 
                        null, 
                        Expression.Constant(value)),
                p));
        }
    }
    

    You can even add additional criteria this way

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

    The very, very hard way

    It would (technically) be possible to rewrite the expression tree before the provider sees it, so you can use the query you had in mind in the first place, but you'd have to

    • create a Where(this IQueryable source, Expression> predicate) to intercept the Queryable.Where,
    • rewrite the expression tree, replacing your CompMethod, wherever it is, with one of the String methods,
    • call the original Queryable.Where with the rewritten expression,
    • and first of all, be able to follow the extension method above in the first place!

    But that's probably way too complicated for what you had in mind.

提交回复
热议问题