在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>%';
另外值得注意的是StartsWith
和EndsWith
类似于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; }