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ù 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ù query[0]
, query[1]
et
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);
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; }