【问题标题】:LINQ to SQL - select where text like string arrayLINQ to SQL - 选择字符串数组之类的文本
【发布时间】:2009-02-04 17:05:32
【问题描述】:

我有一个变量计数的 List<string>,我想查询(通过 LINQ)一个表来查找包含 Text 列中任何这些字符串的任何项目。

试过这个(不起作用):

items = from dbt in database.Items
         where (stringList.FindAll(s => dbt.Text.Contains(s)).Count > 0)
         select dbt;

查询类似于:

select * from items where text like '%string1%' or text like '%string2%'

这可能吗?

【问题讨论】:

    标签: sql linq linq-to-sql sql-like


    【解决方案1】:

    看看这篇文章做你想做的事:
    http://www.albahari.com/nutshell/predicatebuilder.aspx

    这就像一场梦。我基本上剪切并粘贴了他们的代码并将其取回(当然是我自己的数据方案):

    SELECT [t0].[Id], [t0].[DateCreated], [t0].[Name] ...
    FROM [dbo].[Companies] AS [t0]
    WHERE ([t0].[Name] LIKE @p0) OR ([t0].[Name] LIKE @p1)
    

    这是我为概念验证运行的代码:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Linq.Expressions;
    
    namespace PredicateTest
    {
    class Program
    {
        static void Main(string[] args)
        {
            DataClasses1DataContext dataContext = new DataClasses1DataContext();
    
            Program p = new Program();
            Program.SearchCompanies("test", "test2");
            var pr = from pi in  dataContext.Companies.Where(Program.SearchCompanies("test", "test2")) select pi;
        }
    
        DataClasses1DataContext dataContext = new DataClasses1DataContext();
    
        public static Expression<Func<Company, bool>> SearchCompanies(
                                                      params string[] keywords)
        {
            var predicate = PredicateBuilder.False<Company>();
            foreach (string keyword in keywords)
            {
                string temp = keyword;
                predicate = predicate.Or(p => p.Name.Contains(temp));
            }
            return predicate;
        }
    
    }
    
    public static class PredicateBuilder
    {
        public static Expression<Func<T, bool>> True<T>() { return f => true; }
        public static Expression<Func<T, bool>> False<T>() { return f => false; }
    
        public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expr1,
                                                            Expression<Func<T, bool>> expr2)
        {
            var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
            return Expression.Lambda<Func<T, bool>>
                  (Expression.OrElse(expr1.Body, invokedExpr), expr1.Parameters);
        }
    
        public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expr1,
                                                             Expression<Func<T, bool>> expr2)
        {
            var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
            return Expression.Lambda<Func<T, bool>>
                  (Expression.AndAlso(expr1.Body, invokedExpr), expr1.Parameters);
        }
    }
    }
    

    我建议去该网站获取代码和解释。

    (我将留下第一个答案,因为如果您需要 IN 语句,它会很好地工作)

    【讨论】:

      【解决方案2】:

      对于整个 LINQ to SQL 游戏来说有点新意,但是这种语法有帮助吗?

      string[] items = new string[] { "a", "b", "c", "d" };
      
      var items = from i in db.Items
                   where items.Contains(p.text)
                  select i;
      

      来自:

      http://blog.wekeroad.com/2008/02/27/creating-in-queries-with-linq-to-sql/

      【讨论】:

      • 感谢 Matthew 的想法,但这会生成以下 SQL:SELECT [t0].[Text] FROM [dbo].[Table] AS [t0] WHERE [t0].[Text] IN (@p0) 它在数组的每个项目中查找文本列,而不是在文本列中查找数组的每个项目。
      【解决方案3】:

      在阅读这篇文章后,寻找与您相同的解决方案,我找到了一个解决方案,使用 Linq 的 .Any.All 方法是获取数组匹配结果的一种简单而优雅的方法。

      在本例中,我使用搜索输入,以逗号分隔作为示例。我不在乎匹配是否不在同一个案例中。

      var qry = Query.Split(',').Select(c => c.Trim().ToLower());
      

      首先获取一些数据进行查询,从 Linq 到 SQL 或任何地方

      var search = db.tablename;
      

      使用 lambda 语法编写紧凑的代码,并在查询中匹配 .Any 字符串以匹配表中的名称或描述。

      search = search.Where(
          record => 
          qry.Any(q => record.Name.ToLower().Contains(q)) || 
          qry.Any(q => record.Description.ToLower().Contains(q)));
      

      如果您只想要在任何字段中匹配所有字符串的结果,您可以将.Any 替换为.All

      search = search.Where(
          record => 
          qry.All(q => record.Name.ToLower().Contains(q)) || 
          qry.All(q => record.Description.ToLower().Contains(q)));
      

      【讨论】:

        【解决方案4】:

        使用:

        string searh = "test1 test2,test3";    
        data.Persons.Search(p => p.Name, search);
        

        搜索功能是:

        public static IQueryable<T> Search<T>(this IQueryable<T> source, Expression<Func<T, string>> selector, string s)
        {
            if (string.IsNullOrEmpty(s))
                return source;
        
            string[] str = s.Split(new char[] { ' ', ',' }, StringSplitOptions.RemoveEmptyEntries);
        
            MethodInfo methodContains = typeof(string).GetMethod("Contains", new[] { typeof(string) });
        
            Expression strExpression;
            Expression expressionContains;
            Expression resultExpression = Expression.Empty();
        
            for (int i = 0; i < str.Length; i++)
            {
                strExpression = Expression.Constant(str[i].Trim(), typeof(string));
                expressionContains = Expression.Call(selector.Body, methodContains, strExpression);
        
                if (i == 0)
                    resultExpression = expressionContains;
                else
                    resultExpression = Expression.OrElse(resultExpression, expressionContains);
            }
        
            Expression<Func<T, bool>> lambdaExpr = Expression.Lambda<Func<T, bool>>(resultExpression, new ParameterExpression[] { selector.Parameters[0] });
        
            return source.Where(lambdaExpr);
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多