2011-10-07 26 views
16

Quiero buscar esto:Linq to Entities (EF 4.1): ¿Cómo hacer un SQL LIKE con un comodín en el centro ('% term% term%')?

Post Cereal 

y sale esto:

Post Honey Nut Cereal 

donde los comodines serían los espacios.

Sé que podría hacer un SPLIT y una serie de AND y Contiene() y la traducción a un Linq Expression para cada término como un objeto de especificación, pero ¿no hay una forma de respetar los comodines en el término enviado a SQL ? Miré las funciones SQL donde está en Linq a SQL, pero no estoy seguro de lo que es en Linq para Entidades.

me gustaría hacer algo como esto:

term = '%' + term.Replace(' ', '%') + '%'; 
db.table.where(p => System.Data.Objects.SqlClient.SqlFunctions 
        .SqlMethods.Like(p.fieldname, term)); 

¿Alguna sugerencia?

Respuesta

43

creo que podría utilizar SqlFunctions.PatIndex:

dt.Table.Where(p => SqlFunctions.PatIndex(term, p.fieldname) > 0); 

SqlFunctions.PatIndex se comporta igual que el operador SQL LIKE. Es compatible con todos los caracteres comodín estándar incluyendo:

  • % Cualquier cadena de cero o más caracteres.
  • _ (guion bajo) Cualquier carácter simple.
  • [] Cualquier carácter individual dentro del rango especificado ([a-f]) o set ([abcdef]).
  • [^] Cualquier carácter que no esté dentro del rango especificado ([^ a-f]) o set ([^ abcdef]).

SqlFunctions.PatIndex menudo está disponible cuando el SqlMethods.Like no está disponible (incluyendo dentro de los controladores MVC)

+1

Esto merece más votos. Esto funcionó perfectamente para mí sin mucha complejidad. –

+0

El Dr. Zim tiene razón, he estado buscando una solución durante varias horas y esta es, de lejos, la más simple que encontré. – user1841243

+0

Intenté esto en .NET y directamente en TSQL y ninguna de las formas funcionó para mí. El uso de EF 5, .NET 4.5 y VS 2012 – Matt

5

Es probablemente más fácil de pasar por alto LINQ y utilizar un filtro de Entity SQL:

var query - db.table.Where("TRIM(fieldname) LIKE @pattern"); 
query.Parameters.Add(new ObjectParameter("pattern", term)); // term == "%what%ever%" 

y el tipo de implementos queryIQueryable<TEntity> para que pueda aplicar más operadores LINQ.

+0

Estoy probando esto en LINQPad, pero obtengo esta excepción: 'EntitySqlException: 'BusinessName' no se pudo resolver en el ámbito o contexto actual. Asegúrese de que todas las variables referenciadas estén dentro del alcance, que los esquemas requeridos estén cargados, y que los espacios de nombres estén referenciados correctamente. Donde "BusinessName" es la columna en la que intento filtrar. No puedo entender cómo superar esto. –

+0

@adrift Necesita configurar LINQPad con la información de contexto, apenas lo uso, así que no puedo ayudar (IIRC Acabo de hacer referencia al ensamblado con los tipos de contexto y entidad). – Richard

+1

El uso de Entity SQL es, de hecho, la única forma de hacerlo: L2E no admite este tipo de búsqueda de comodines. Para solucionar su problema, intente utilizar 'it.BusinessName'. Las columnas en ESQL deben estar prefijadas y 'it' es el prefijo predeterminado - [aquí] (http://stackoverflow.com/questions/6202036/entity-framework-v4-1-like/6202346#6202346) es un ejemplo completo de la consulta . –

0

Solo para aclarar el comentario de Ladislav respecto it.BusinessName. Creo que a lo que se refiere es prefijando el nombre del campo con .it. La solución anterior funciona siempre que prefija el nombre del campo en la cláusula where con it.. Además, no necesitaba el TRIM() en mi caso.

var query - db.table.Where("it.fieldname LIKE @pattern"); 
query.Parameters.Add(new ObjectParameter("pattern", term)); // term == "%what%ever%" 

Funcionó perfectamente en una base de datos Oracle.

Cuestiones relacionadas