L'utilisation contains () dans LINQ to SQL
-
24-09-2019 - |
Question
Je suis en train de mettre en œuvre une recherche par mot clé très basique dans une application utilisant LINQ to SQL. Mes termes de recherche sont dans un tableau de chaînes, chaque élément de réseau étant un mot, et je voudrais trouver les lignes qui contiennent les termes de recherche. Je ne me dérange pas si elles contiennent plus que les termes de recherche (plus probablement, ils), mais tous les termes de recherche ne doivent être présents.
Idéalement, je voudrais quelque chose de similaire à l'extrait ci-dessous, mais je sais que cela ne fonctionnera pas. De plus, je l'ai regardé cette question ici , mais l'auteur de cette question semble se contenter de faire les choses dans l'autre sens (query.Contains(part.partName)
), qui ne fonctionne pas pour moi.
public IQueryable<Part> SearchForParts(string[] query)
{
return from part in db.Parts
where part.partName.Contains(query)
select part;
}
Comment puis-je réécrire cette requête afin qu'il fera ce que je dois?
La solution
En regardant les autres tentatives me attriste: (
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;
}
Hypothèses:
-
partName ressemble à: "ABC 123 XYZ"
-
requête est { "ABC", "123", "XY"}
Autres conseils
Une solution plus simple et plus correcte (alors leppie de):
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;
}
Cela fonctionne aussi longtemps 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)
, partName
est recherché toute occurrence de qs
. Le SQL résultant serait équivalent (où qs
):
select * from Parts where partName like '%<qs>%';
A noter également StartsWith
et EndsWith
qui sont semblables à Contains
mais regardez la chaîne dans l'emplacement spécifique.
query.Contains(partName)
est identique à une commande SQL in
. Le SQL résultant serait équivalent à (où query[0]
, query[1]
et
select * from Parts where partName in ( <query0>, <query1>, ..., <queryN> );
Mise à jour:
Il est également important de noter que la réponse de leppie n'échappe pas les caractères génériques avant de les ajouter à la balise comme déclaration . Ce n'est pas un problème avec la solution Contains
depuis Linq va échapper à la requête avant de l'envoyer. Une version échappée de la solution SqlMethods.Like
serait:
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;
}
Vous n'avez pas à vous soucier »depuis Linq échappera pour vous.
Vous pouvez essayer:
public IQueryable<Part> SearchForParts(string[] 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 sera en mesure de le transformer en T-SQL. Une autre option serait:
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;
}
Il est pas aussi joli, mais il devrait fonctionner. Vous obtiendrez une requête avec beaucoup de AND
s dans la clause where.
Vous pouvez l'écrire comme cela
var result = db.Parts.Where(p => query.All(q => p.partName.Contains(q)));
Utilisation du package NinjaNye.SearchExtension NuGet vous permet d'effectuer cette recherche avec facilité:
string[] 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 effectuer une RankedSearch
qui retourne IQueryable<IRanked<T>>
qui comprend simplement une propriété qui montre combien de fois les termes de recherche apparaissent:
//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 y a un guide plus vaste sur les projets Page GitHub: https://github.com/ninjanye/SearchExtensions
Hope this helps futurs visiteurs
Je pense que c'est un peu simple et de travail pour moi:
string[] product = products.Split(',');
using (var context = new ProjectTrackerEntities())
{ var result = from part in context.DBAudits where product.Contains(part.TableName) select part; }
S'il vous plaît essayez ceci:
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;
}