Usando contiene () en LINQ a SQL
-
24-09-2019 - |
Pregunta
Estoy tratando de poner en práctica una búsqueda de palabras clave muy básico en una aplicación usando linq-to-sql. Mis términos de búsqueda están en una matriz de cadenas, siendo cada elemento de la matriz una palabra, y me gustaría encontrar las filas que contienen los términos de búsqueda. No me importa si contienen algo más que los términos de búsqueda (lo más probable es que lo hará), pero todos los términos de búsqueda tiene que estar presente.
Idealmente, me gustaría algo similar a lo siguiente fragmento de código, pero sé que esto no va a funcionar. Además, he mirado esta pregunta aquí , pero el autor de esa pregunta parece contento de hacer las cosas al revés (query.Contains(part.partName)
), lo que no funciona para mí.
public IQueryable<Part> SearchForParts(string[] query)
{
return from part in db.Parts
where part.partName.Contains(query)
select part;
}
¿Cómo puedo volver a escribir esta consulta para que hará lo que yo necesito?
Solución
En cuanto a los otros intentos entristece mí: (
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;
}
Los supuestos:
-
miradas partName como: "ABC 123 XYZ"
-
{consulta es "ABC", "123", "XY"}
Otros consejos
Una solución más simple y más correcta (luego de 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;
}
Esto funcionará siempre y cuando partName
es una cadena (o un equivalente SQL de una cadena).
Lo importante a destacar es partName.Contains(qs)
es diferente de query.Contains(partName)
.
Con partName.Contains(qs)
, partName
se busca cualquier aparición de qs
. El SQL resultante sería equivalente (donde qs
):
select * from Parts where partName like '%<qs>%';
También hay que resaltar son StartsWith
y EndsWith
que son similares a Contains
sino buscar la cadena en el lugar específico.
query.Contains(partName)
es lo mismo que un in
de comandos SQL . El SQL resultante sería equivalente a (donde query[0]
, query[1]
, y
select * from Parts where partName in ( <query0>, <query1>, ..., <queryN> );
Actualización:
También es importante tener en cuenta que la respuesta de leppie no escapa a los caracteres comodín antes de añadirlos a la como declaración . Este no es un problema con la solución Contains
desde LINQ escapará a la consulta antes de enviarlo. Una versión escapado de la solución SqlMethods.Like
sería:
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;
}
Usted no tiene que preocuparse acerca de "LINQ desde escapará por usted.
Usted podría intentar:
public IQueryable<Part> SearchForParts(string[] query)
{
return from part in db.Parts
where query.All(term => part.partName.Contains(term))
select part;
}
Sin embargo, no estoy seguro de si LINQ a SQL será capaz de transformarlo en T-SQL. Otra opción sería la siguiente:
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;
}
No es tan bonito, pero debería funcionar. Usted obtendrá una consulta con una gran cantidad de AND
s en la cláusula where.
Se puede escribir como este
var result = db.Parts.Where(p => query.All(q => p.partName.Contains(q)));
Usando el paquete NinjaNye.SearchExtension Nuget le permite realizar esta búsqueda con facilidad:
string[] terms = new[]{"search", "term", "collection"};
var result = db.Parts.Search(terms, p => p.PartName);
También puede buscar en varias propiedades de cadena
var result = db.Parts.Search(terms, p => p.PartName, p.PartDescription);
O realizar una RankedSearch
que devuelve IQueryable<IRanked<T>>
que simplemente se incluye una propiedad que muestra cuántas veces aparecían los términos de búsqueda:
//Perform search and rank results by the most hits
var result = db.Parts.RankedSearch(terms, p => p.PartName, p.PartDescription)
.OrderByDescending(r = r.Hits);
Hay una más amplia guía sobre los proyectos de la página de GitHub: https://github.com/ninjanye/SearchExtensions
Espero que esto ayude a los futuros visitantes
Siento que esto es algo simple y trabajando para mí:
string[] product = products.Split(',');
using (var context = new ProjectTrackerEntities())
{ var result = from part in context.DBAudits where product.Contains(part.TableName) select part; }
Por favor, intente lo siguiente:
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;
}