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?

¿Fue útil?

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 es el valor de 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 es el valor de query[0], es el valor de query[1], y es el último valor en la matriz de consulta):

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 ANDs 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;
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top