代码之家  ›  专栏  ›  技术社区  ›  a_m0d

在linq to sql中使用contains()

  •  37
  • a_m0d  · 技术社区  · 14 年前

    我正在尝试使用linq to sql在应用程序中实现一个非常基本的关键字搜索。我的搜索项位于字符串数组中,每个数组项都是一个单词,我希望找到包含搜索项的行。我不介意它们包含的不仅仅是搜索词(很可能,它们会),但是所有的搜索词都必须存在。

    理想情况下,我希望类似于下面的片段,但我知道这是行不通的。我也看过 this question here ,但这个问题的作者似乎满足于做相反的事情( query.Contains(part.partName) )这对我不起作用。

    public IQueryable<Part> SearchForParts(string[] query)
    {
        return from part in db.Parts
               where part.partName.Contains(query)
               select part;
    }
    

    如何重写此查询以使其执行所需的操作?

    7 回复  |  直到 10 年前
        1
  •  40
  •   leppie    14 年前

    看着其他的尝试让我难过:(

    public IQueryable<Part> SearchForParts(string[] query)
    {
      var q = db.Parts.AsQueryable(); 
    
      foreach (var qs in query)
      { 
        var likestr = string.Format("%{0}%", qs);
        q = q.Where(x => SqlMethods.Like(x.partName, likestr));
      }
    
      return q;
    }
    

    假设:

    • 部件名称如下:“ABC 123 XYZ”

    • 查询是{“abc”,“123”,“xy”}

        2
  •  19
  •   Trisped    10 年前

    更简单、更正确的解决方案(然后是Leppie的):

    public IQueryable<Part> SearchForParts(string[] query)
    {
        var q = db.Parts.AsQueryable(); 
    
        foreach (string qs in query)
        {
            q = q.Where(x => x.partName.Contains(qs));
        }
    
        return q;
    }
    

    只要 partName 是字符串(或字符串的SQL等价物)。

    重要的是 partName.Contains(qs) 不同于 query.Contains(partName) .
    零件名称.包含(qs) , 零件名称 搜索是否有 qs . 生成的sql是等价的(其中,<qs>是 QS ):

    select * from Parts where partName like '%<qs>%';
    

    值得注意的还有 StartsWith EndsWith 类似于 Contains 但要在特定位置查找字符串。

    query.contains(部件名) 与SQL相同 in 命令。生成的sql相当于(其中,<query0>是 query[0] ,<query1>是 query[1] ,并且<queryn>是查询数组中的最后一个值):

    select * from Parts where partName in ( <query0>, <query1>, ..., <queryN> );
    

    更新:
    还要注意的是,leppie的答案在将通配符添加到 like 语句。这与 Contains 解决方案,因为linq将在发送查询之前对其进行转义。转义版本的 SqlMethods.Like 解决办法是:

    public IQueryable<Part> SearchForParts(string[] query)
    {
        var q = db.Parts.AsQueryable(); 
    
        foreach (var qs in query)
        {
            string escaped_bs = qs.Replace("/", "//"),
                escaped_us = escaped_bs.Replace("_", "/_"),
                escaped_p = escaped_us.Replace("%", "/%"),
                escaped_br = escaped_p.Replace("[", "/["),
                likestr = string.Format("%{0}%", escaped_br);
    
            q = q.Where(x => SqlMethods.Like(x.partName, likestr, '/'));
        }
    
        return q;
    }
    

    你不必担心,因为林克会替你逃走的。

        3
  •  2
  •   Rory    14 年前

    你可以试试:

    public IQueryable<Part> SearchForParts(string[] query)
    {
        return from part in db.Parts
               where query.All(term => part.partName.Contains(term))
               select part;
    }
    

    但是,我不确定linq to sql是否能够将其转换为t-sql。另一个选择是:

    public IQueryable<Part> SearchForParts(string[] query)
    {
        var result = from part in db.Parts
                     select part;
    
        foreach(var term in query)
        {
            result = from part in result
                     where part.partName.Contains(term)
                     select part;
        }
    
        return result;
    }
    

    虽然没那么漂亮,但应该管用。你会得到一个有很多 AND 在where子句中。

        4
  •  1
  •   Fadrian Sudaman    14 年前

    你可以这样写

    var result = db.Parts.Where(p => query.All(q => p.partName.Contains(q)));
    
        5
  •  1
  •   NinjaNye    10 年前

    使用 NinjaNye.SearchExtension NuGet包允许您轻松执行此搜索:

    string[] terms = new[]{"search", "term", "collection"};
    var result = db.Parts.Search(terms, p => p.PartName);
    

    还可以搜索多个字符串属性

    var result = db.Parts.Search(terms, p => p.PartName, p.PartDescription);
    

    或表演 RankedSearch 又回来了 IQueryable<IRanked<T>> 其中包含一个属性,该属性显示搜索词出现的次数:

    //Perform search and rank results by the most hits
    var result = db.Parts.RankedSearch(terms, p => p.PartName, p.PartDescription)
                         .OrderByDescending(r = r.Hits);
    

    在项目github页面上有一个更广泛的指南: https://github.com/ninjanye/SearchExtensions

    希望这能帮助未来的游客

        6
  •  0
  •   Bo Persson tox    12 年前

    我觉得这对我来说有点简单:

    string[] product = products.Split(','); 
    using (var context = new ProjectTrackerEntities()) 
    { var result = from part in context.DBAudits where product.Contains(part.TableName) select part; }
    
        7
  •  -3
  •   masoud ramezani    14 年前

    请试试这个:

    public IQueryable<Part> SearchForParts(string[] query)
    {
        return from part in db.Parts
               where Search(part.Name,query)
               select part;
    }
    
    public bool Search(string partName,string[] query)
    {
        for (int i = 0; i < query.Length; i++)
        {
            if(partName.Contains(query[i]))
               return true;
        }
    
        return false;
    }