LINQ for LIKE queries of array elements

后端 未结 5 1253
臣服心动
臣服心动 2020-12-30 16:01

Let\'s say I have an array, and I want to do a LINQ query against a varchar that returns any records that have an element of the array anywhere in the varchar.

Somet

相关标签:
5条回答
  • 2020-12-30 16:29

    it will work if you build up the query as follows:

    var query = from c in contacts.AsEnumerable() select c;

    query = query.Where(c=> (c.Industry.Contains("airline")) || (c.Industry.Contains("railroad")));

    you just need to programmatically generate the string above if the parameters airline and railroad are user inputs. This was in fact a little more complicated than I was expecting. See article - http://www.albahari.com/nutshell/predicatebuilder.aspx

    0 讨论(0)
  • 2020-12-30 16:32

    IEnumerable.Contains() translates to SQL IN as in:

    WHERE 'american airlines' IN ('airline', 'railroad') -- FALSE
    

    String.Contains() which translates to SQL LIKE %...% as in:

    WHERE 'american airlines' LIKE '%airline%' -- TRUE
    

    If you want the contacts where the contact's industry is LIKE (contains) any of the given industries, you want to combine both Any() and String.Contains() into something like this:

    string[] industries = { "airline", "railroad" };
    
    var query = from c in contacts 
                where industries.Any(i => c.Industry.Contains(i))
                select c;
    

    However, combining both Any() and String.Contains() like this is NOT supported in LINQ to SQL. If the set of given industries is small, you can try something like:

    where c.Industry.Contains("airline") ||
          c.Industry.Contains("railroad") || ...
    

    Or (although normally not recommended) if the set of contacts is small enough, you could bring them all from the DB and apply the filter with LINQ to Objects by using contacts.AsEnumerable() or contacts.ToList() as the source of the query above:

    var query = from c in contacts.AsEnumerable()
                where industries.Any(i => c.Industry.Contains(i))
                select c;
    
    0 讨论(0)
  • 2020-12-30 16:32

    Unfortunately, LIKE is not supported in LINQ to SQL as per here:

    http://msdn.microsoft.com/en-us/library/bb882677.aspx

    To get around this, you will have to write a stored procedure which will accept the parameters you want to use in the like statement(s) and then call that from LINQ to SQL.


    It should be noted that a few of the answers suggest using Contains. This won't work because it looks to see that the entire string matches the array element. What is being looked for is for the array element to be contained in the field itself, something like:

    industry LIKE '%<element>%'
    

    As Clark has mentioned in a comment, you could use a call to IndexOf on each element (which should translate to a SQL call):

    string[] industries = { "airline", "railroad" }
    
    var query = 
        from c in contacts 
        where
            c.industry.IndexOf(industries[0]) != -1 ||
            c.industry.IndexOf(industries[1]) != -1
    

    If you know the length of the array and the number of elements, then you could hard-code this. If you don't, then you will have to create the Expression instance based on the array and the field you are looking at.

    0 讨论(0)
  • 2020-12-30 16:35
    from c in contracts 
    where industries.Any(i => i == c.industry)
    select c;
    

    something like that. use the any method on the collection.

    0 讨论(0)
  • 2020-12-30 16:40

    This is actually an example I use in my "Express Yourself" presentation, for something that is hard to do in regular LINQ; As far as I know, the easiest way to do this is by writing the predicate manually. I use the example below (note it would work equally for StartsWith etc):

        using (var ctx = new NorthwindDataContext())
        {
            ctx.Log = Console.Out;
            var data = ctx.Customers.WhereTrueForAny(
                s => cust => cust.CompanyName.Contains(s),
                "a", "de", "s").ToArray();
        }
    // ...
    public static class QueryableExt
    {
        public static IQueryable<TSource> WhereTrueForAny<TSource, TValue>(
            this IQueryable<TSource> source,
            Func<TValue, Expression<Func<TSource, bool>>> selector,
            params TValue[] values)
        {
            return source.Where(BuildTrueForAny(selector, values));
        }
        public static Expression<Func<TSource, bool>> BuildTrueForAny<TSource, TValue>(
            Func<TValue, Expression<Func<TSource, bool>>> selector,
            params TValue[] values)
        {
            if (selector == null) throw new ArgumentNullException("selector");
            if (values == null) throw new ArgumentNullException("values");
            if (values.Length == 0) return x => true;
            if (values.Length == 1) return selector(values[0]);
    
            var param = Expression.Parameter(typeof(TSource), "x");
            Expression body = Expression.Invoke(selector(values[0]), param);
            for (int i = 1; i < values.Length; i++)
            {
                body = Expression.OrElse(body,
                    Expression.Invoke(selector(values[i]), param));
            }
            return Expression.Lambda<Func<TSource, bool>>(body, param);
        }
    
    }
    
    0 讨论(0)
提交回复
热议问题