uso operador not c# linq-to-sql contains keyword-search

not - operador like en linq c#



Usando contains() en LINQ to SQL (7)

Estoy tratando de implementar una búsqueda de palabras clave muy básica en una aplicación que usa linq-to-sql. Mis términos de búsqueda están en una serie de cadenas, cada elemento de matriz es una palabra, y me gustaría encontrar las filas que contienen los términos de búsqueda. No me importa si contienen más que solo los términos de búsqueda (lo más probable es que lo hagan), pero todos los términos de búsqueda deben estar presentes.

Idealmente, quisiera algo similar al fragmento a continuación, pero sé que esto no funcionará. Además, he analizado esta pregunta aquí , pero el autor de esa pregunta parece contento de hacer las cosas al revés ( query.Contains(part.partName) ), 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 haga lo que necesito?


Puedes escribirlo así

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


Siento que esto es algo simple y que funciona 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; }


Tu podrías 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 to SQL podrá transformarlo en T-SQL. Otra opción sería:

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. Obtendrá una consulta con muchos AND en la cláusula where.


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 que partName sea ​​una cadena (o un SQL equivalente de una cadena).

Lo importante a tener en cuenta es partName.Contains(qs) es diferente de query.Contains(partName) .
Con partName.Contains(qs) , se busca partName para cualquier ocurrencia de qs . El SQL resultante sería equivalente (donde <qs> es el valor de qs ):

select * from Parts where partName like ''%<qs>%'';

También deben StartsWith cuenta StartsWith y EndsWith que son similares a partName.Contains(qs) pero busca la cadena en la ubicación específica.

query.Contains(partName) es lo mismo que un SQL in comando. El SQL resultante sería equivalente a (donde <query0> es el valor de la query[0] , <query1> es el valor de la query[1] , y <queryN> es el último valor en la matriz de consulta):

select * from Parts where partName in ( <query0>, <query1>, ..., <queryN> );

Actualizar:
También es importante tener en cuenta que la respuesta de Leppie no escapa a los caracteres comodín antes de agregarlos a la declaración like . Esto no es un problema con la solución query.Contains(partName) ya que Linq escapará de la consulta antes de enviarla. Una versión escapada 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; }

No tiene que preocuparse ''ya que Linq lo escapará por usted.


Usar el paquete NinjaNye.SearchExtension NinjaNye.SearchExtension 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 múltiples propiedades de cadenas

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

O realice un RankedSearch que devuelve IQueryable<IRanked<T>> que simplemente incluye una propiedad que muestra cuántas veces aparecieron 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 guía más extensa en la página de proyectos GitHub: https://github.com/ninjanye/SearchExtensions

Espero que esto ayude a los futuros visitantes


Ver los otros intentos me entristece :(

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; }

Suposiciones

  • partName se ve así: "ABC 123 XYZ"

  • consulta es {"ABC", "123", "XY"}


por favor intente esto:

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; }