Utilisation de contains () dans LINQ to SQL

J’essaie d’implémenter une recherche par mot clé très simple dans une application utilisant linq-to-sql. Mes termes de recherche sont dans un tableau de chaînes, chaque élément du tableau étant un mot, et j’aimerais trouver les lignes contenant les termes de recherche. Cela ne me dérange pas s’ils contiennent plus que les termes de recherche (probablement, ils le feront), mais tous les termes de recherche doivent être présents.

Idéalement, j’aimerais quelque chose de similaire à l’extrait ci-dessous, mais je sais que cela ne fonctionnera pas. En outre, j’ai examiné cette question ici , mais l’auteur de cette question semble se contenter de faire les choses dans l’autre sens ( query.Contains(part.partName) ), ce qui ne fonctionne pas pour moi.

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

Comment puis-je réécrire cette requête pour qu’elle fasse ce dont j’ai besoin?

Regarder les autres tentatives m’atsortingste 🙁

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

Hypothèses:

  • partName ressemble à: “ABC 123 XYZ”

  • la requête est {“ABC”, “123”, “XY”}

Une solution plus simple et plus correcte (alors leppie’s):

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

Cela fonctionnera tant que partName est une chaîne (ou un équivalent SQL d’une chaîne).

La chose importante à noter est partName.Contains(qs) est différent de query.Contains(partName) .
Avec partName.Contains(qs) , la recherche de partName est recherchée pour toute occurrence de qs . Le SQL résultant serait équivalent (où est la valeur de qs ):

 select * from Parts where partName like '%%'; 

Notons également StartsWith et EndsWith qui sont similaires à Contains mais recherchent la chaîne dans un emplacement spécifique.

query.Contains(partName) est identique à une commande SQL. Le SQL résultant serait équivalent à (où est la valeur de la query[0] , est la valeur de la query[1] et est la dernière valeur du tableau de requête):

 select * from Parts where partName in ( , , ...,  ); 

Mettre à jour:
Il est également important de noter que la réponse de leppie n’échappe pas aux caractères génériques avant de les append à l’instruction like . Ce n’est pas un problème avec la solution Contains car Linq échappera à la requête avant de l’envoyer. Une version échappée de la solution SqlMethods.Like serait:

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

Vous n’avez pas à vous soucier de ce que Linq vous échappera.

Tu pourrais essayer:

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

Cependant, je ne suis pas sûr que LINQ to SQL puisse le transformer en T-SQL. Une autre option serait:

 public IQueryable SearchForParts(ssortingng[] 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; } 

Ce n’est pas aussi joli, mais ça devrait marcher. Vous obtiendrez une requête avec beaucoup de AND dans la clause where.

Vous pouvez l’écrire comme ceci

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

L’utilisation du package nuget NinjaNye.SearchExtension vous permet d’effectuer cette recherche en toute simplicité:

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

Vous pouvez également rechercher plusieurs propriétés de chaîne

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

Ou effectuez une recherche de RankedSearch qui renvoie IQueryable> qui inclut simplement une propriété indiquant combien de fois les termes de recherche sont apparus:

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

Il existe un guide plus complet sur la page des projets GitHub: https://github.com/ninjanye/SearchExtensions

J’espère que cela aidera les futurs visiteurs

Je pense que c’est un peu simple et que je travaille pour moi:

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

veuillez essayer ceci:

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