2009-01-11 17 views

Respuesta

84

Si está utilizando una colección en memoria como filtro, probablemente sea mejor usar la negación de Contiene(). Tenga en cuenta que esto puede fallar si la lista es demasiado larga, en cuyo caso tendrá que elegir otra estrategia (consulte a continuación el uso de una estrategia para una consulta totalmente orientada a BD).

var exceptionList = new List<string> { "exception1", "exception2" }; 

    var query = myEntities.MyEntity 
         .Select(e => e.Name) 
         .Where(e => !exceptionList.Contains(e.Name)); 

Si está excluyendo basado en otra consulta de base de datos utilizando Except podría ser una mejor elección. (Aquí es un link a las extensiones conjunto admitido en LINQ a Entidades)

var exceptionList = myEntities.MyOtherEntity 
           .Select(e => e.Name); 

    var query = myEntities.MyEntity 
         .Select(e => e.Name) 
         .Except(exceptionList); 

Esto supone una entidad compleja en la que se está excluyendo a algunos que en función alguna propiedad de otra mesa y desea que los nombres de las entidades que no son excluido Si deseaba la entidad completa, tendría que construir las excepciones como instancias de la clase de entidad de modo que satisfaga el operador de igualdad predeterminado (consulte docs).

+1

Por alguna razón 'Except' produce horribles SQL . 'Contains' es el método a usar aquí:' myEntities.MyEntity.Select (e => e.Name) .Where (x =>! ExceptionList.Contains (x)) '. –

+0

@GertArnold, ¿podría por favor elaborar la declaración "produce SQL horrible"? Estoy usando Except, y está funcionando bien. Sin rarezas, ni peculiaridades de rendimiento, AFAIK. – NinjaCross

+0

@NinjaCross Una instrucción como en la respuesta anterior produce SQL con n-1 cláusulas 'UNION ALL', donde n es el número de elementos en' exceptionList'. Lo intenté con EF 6.1, así que no es que haya mejorado o algo así. En EF 4.1 es lo mismo, así que no entiendo por qué esta respuesta ha sido aceptada alguna vez. La respuesta que propone 'Contiene' es la correcta. Creo que usaste 'Except' con otro' IQueryable' para que EF pueda traducirlo a SQL 'EXCEPT'. ¿Tuviste? –

14

Probar:

from p in db.Products 
where !theBadCategories.Contains(p.Category) 
select p; 

¿Qué es la consulta SQL que desea traducir en una consulta LINQ?

4

Tomé una lista y se utiliza,

!MyList.Contains(table.columb.tostring()) 

Nota: Asegúrese de utilizar la lista y no iList

5

tengo los siguientes métodos de extensión:

public static bool IsIn<T>(this T keyObject, params T[] collection) 
    { 
     return collection.Contains(keyObject); 
    } 

    public static bool IsIn<T>(this T keyObject, IEnumerable<T> collection) 
    { 
     return collection.Contains(keyObject); 
    } 

    public static bool IsNotIn<T>(this T keyObject, params T[] collection) 
    { 
     return keyObject.IsIn(collection) == false; 
    } 

    public static bool IsNotIn<T>(this T keyObject, IEnumerable<T> collection) 
    { 
     return keyObject.IsIn(collection) == false; 
    } 

Uso:

var inclusionList = new List<string> { "inclusion1", "inclusion2" }; 
var query = myEntities.MyEntity 
        .Select(e => e.Name) 
        .Where(e => e.IsIn(inclusionList)); 

var exceptionList = new List<string> { "exception1", "exception2" }; 
var query = myEntities.MyEntity 
        .Select(e => e.Name) 
        .Where(e => e.IsNotIn(exceptionList)); 

Muy útil también cuando se pasa directamente valores:

var query = myEntities.MyEntity 
        .Select(e => e.Name) 
        .Where(e => e.IsIn("inclusion1", "inclusion2")); 

var query = myEntities.MyEntity 
        .Select(e => e.Name) 
        .Where(e => e.IsNotIn("exception1", "exception2")); 
+0

Es útil, pero no se puede traducir a la expresión de la tienda. –

+0

@MarekBar Siempre puede usar .AsEnumerable() antes del Where() .. – JoanComasFdz

+0

Correcto, pero me gustaría ejecutar en la base de datos. AsEnumerable cargará datos en la memoria. –

0

he creado de una manera más similar a la de SQL, creo que es más fácil de entender

var list = (from a in listA.AsEnumerable() 
      join b in listB.AsEnumerable() on a.id equals b.id into ab 
      from c in ab.DefaultIfEmpty() 
      where c != null 
      select new { id = c.id, name = c.nome }).ToList();