在LINQ to SQL中使用contains()

我试图在一个使用linq-to-sql的应用程序中实现一个非常基本的关键字search。 我的search条件是在一个string数组中,每个数组项是一个单词,我想查找包含search条件的行。 我不介意,如果他们不仅仅包含search条件(很可能,他们会),但所有的search条件必须存在。

理想情况下,我想要类似下面的代码片段,但我知道这是行不通的。 另外,我在这里看到了这个问题 ,但是这个问题的作者似乎满足于做相反的事情( query.Contains(part.partName) ),这对我不起作用。

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

我怎样才能重写这个查询,以便它能做我需要的?

看着其他尝试伤心我:(

 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; } 

假设:

  • partName看起来像:“ABC 123 XYZ”

  • 查询是{“ABC”,“123”,“XY”}

一个更简单,更正确的解决scheme(然后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是一个string(或者一个string的SQL等价物),就可以工作。

重要的是要注意partName.Contains(qs)不同于query.Contains(partName)
使用partName.Contains(qs) ,可以searchpartName中任何出现的qs 。 生成的SQL将是等效的(其中<qs>是qs的值):

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

另外值得注意的是StartsWithEndsWith类似于Contains但在特定位置查找string。

query.Contains(partName)与SQL in命令相同。 生成的SQL将等同于(其中<query0>是query[0]的值,<query1>是query[1]的值,而<queryN>是查询数组中的最后一个值):

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

更新:
注意到,在将它们添加到相似的语句之前,leppie的回答并不会逃避通配符。 这对Contains解决scheme来说不是问题,因为Linq在发送之前会转义查询。 SqlMethods.Like解决scheme的转义版本将是:

 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; } 

你不必担心,因为Linq会为你逃脱。

你可以尝试:

 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。 另一种select是:

 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; } 

这不是很好,但它应该工作。 你会在where子句中得到一个带有很多AND的查询。

你可以这样写

 var result = db.Parts.Where(p => query.All(q => p.partName.Contains(q))); 

使用NinjaNye.SearchExtension nuget包,您可以轻松执行此search:

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

您也可以search多个string属性

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

或者执行一个返回IQueryable<IRanked<T>>RankedSearch ,它只是包含一个显示search条件出现次数的属性:

 //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

希望这有助于未来的游客

我觉得这有点简单,为我工作:

 string[] product = products.Split(','); using (var context = new ProjectTrackerEntities()) { var result = from part in context.DBAudits where product.Contains(part.TableName) select part; } 

请试试这个:

 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; }