Pregunta

Tengo la siguiente consulta LINQ:

var aKeyword = "ACT";
var results = from a in db.Activities
              where a.Keywords.Split(',').Contains(aKeyword) == true
              select a;

Palabras clave es un campo delimitado por comas.

Cada vez que funciono con esta pregunta me sale el siguiente error:

"LINQ a Entidades no reconoce el método 'Boolean Contiene [String] (System.Collections.Generic.IEnumerable`1 [System.String], System.String)' método, y este método no puede ser traducido en una expresión tienda ".

¿Qué es la alternativa para lo que yo estoy tratando de hacer?

¿Fue útil?

Solución

En respuesta a sus consideraciones de rendimiento en un gran conjunto de datos:

Se le va a hacer no coincidencia de cadenas comodín indexada en el cliente, de modo que sí, no habrá pérdida de rendimiento.

¿Hay una razón por la cual tiene varias palabras clave en un campo de tabla? Se podría normalizar eso, para tener una mesa ActivityKeywords donde para cada actividad tiene un número de registros de palabras clave.

Actividades (activity_id, ... / * quitar palabras clave campo * /) ---> ActivityKeywords (activity_id, keyword_id) ---> Palabras clave (keyword_id, valor)

Salida no la primera forma normal: http://en.wikipedia.org/wiki/Database_normalization

EDIT: Además, incluso si tuviera que seguir con una columna, hay una manera de hacer todo serverside (si tiene una sintaxis estricta: 'keyword1, keyword2, ..., keywordN'):

var aKeyword = "ACT";
var results = (from a in db.Activities
              where a.Keywords.Contains("," + aKeyword) || a.Keywords.Contains(aKeyword + ",")
              select a;

Otros consejos

Su problema es que LINQ-a-ENTIDADES tiene que traducir todo lo que se le da en SQL para enviar a la base de datos.

Si eso es realmente lo que tiene que hacer, tendrá que forzar LINQ a Entidades para tirar hacia atrás todos los datos y LINQ a objetos para evaluar la condición.

Ejemplo:

var aKeyword = "ACT";
var results = from a in db.Activities.ToList()
              where a.Keywords.Split(',').Contains(aKeyword) == true
              select a;

Tenga en cuenta sin embargo, que esto va a tirar de todos los objetos de la mesa de actividades. Una alternativa puede ser la de dejar que el DB hacer un poco de un filtro inicial, y filtrar por el resto del camino después:

var aKeyword = "ACT";
var results = (from a in db.Activities
              where a.Keywords.Contains(aKeyword)
              select a).ToList().Where(a => a.KeyWords.Split(',').Contains(aKeyword));

que le permitirá LINQ a Entidades do el filtro se entiende (string.Contains se convierte en una consulta como) que filtrará hacia abajo algunos de los datos, a continuación, aplicar el filtro de bienes que desea a través de LINQ a objetos una vez que haya los objetos de la espalda. Los ToList () de llamadas fuerzas LINQ a Entidades para ejecutar la consulta y construir los objetos, permitiendo LINQ a objetos a ser el motor que hace la segunda parte de la consulta.

Mi conjetura es la forma en la que está llamando Split. Se debe tomar una matriz. Tal vez hay otra división en LINQ está encontrando y que le da un error inusual:

Esto funciona para LINQ a Objetos:

 var dataStore = new List<string>
                    {
                        "foo,bar,zoo",
                        "yelp,foo",
                        "fred",
                        ""
                    };
 var results = from a in dataStore
               where a.Split(new[] {','}).Contains("foo")
               select a;

 foreach (var result in results)
 {
     Console.WriteLine("Match: {0}", result);
 }

Salidas lo siguiente:

Match: foo,bar,zoo
Match: yelp,foo

En realidad, pensando en ello, ¿necesita la división en absoluto? a.Contains("foo") puede ser suficiente para usted (a menos que no desea golpear foobar).

Es posible que desee vistazo a esta pregunta acerca de L2E y .Contains para una solución que debería ser más eficiente que adivinar un superconjunto antes de filtrar el lado del cliente.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top