2009-01-11 10 views

Répondre

84

Si vous utilisez une collection en mémoire comme filtre, il est probablement préférable d'utiliser la négation de Contains(). Notez que cela peut échouer si la liste est trop longue, auquel cas vous devrez choisir une autre stratégie (voir ci-dessous pour l'utilisation d'une stratégie pour une requête entièrement orientée DB).

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

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

Si vous excluez basé sur une autre requête de base de données en utilisant Except pourrait être un meilleur choix. (Voici un link aux extensions Set pris en charge dans LINQ to Entities)

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

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

Cela suppose une entité complexe dans lequel vous excluez certains d'entre eux selon une propriété d'une autre table et que vous voulez les noms des entités qui ne sont pas exclu. Si vous vouliez l'entité entière, vous devez alors construire les exceptions en tant qu'instances de la classe d'entité de sorte qu'elles satisfassent l'opérateur d'égalité par défaut (voir docs).

+1

Pour une raison quelconque 'Except' produit horribles SQL . 'Contains' est la méthode à utiliser ici:' myEntities.MyEntity.Select (e => e.Name) .Where (x =>! ExceptionList.Contains (x)) '. –

+0

@GertArnold, pourriez-vous s'il vous plaît élaborer la déclaration "produit horrible SQL"? J'utilise Except, et ça marche très bien. Pas de bizarreries, ni de défauts de performance, AFAIK. – NinjaCross

+0

@NinjaCross Une instruction comme dans la réponse ci-dessus produit SQL avec n-1 clauses UNION ALL, où n est le nombre d'éléments dans 'exceptionList'. Je viens d'essayer avec EF 6.1, donc ce n'est pas que ça s'est amélioré ou quelque chose comme ça. Dans EF 4.1 c'est la même chose, donc je ne comprends tout simplement pas pourquoi cette réponse a été acceptée. La réponse proposant «Contient» est la bonne. Je pense que vous avez utilisé 'Except' avec un autre' IQueryable', donc EF a pu le traduire en SQL 'EXCEPT'. As tu? –

14

Essayez:

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

Quelle est la requête SQL que vous souhaitez traduire dans une requête Linq?

4

Je pris une liste et utilisé,

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

Remarque: Assurez-vous d'utiliser la liste et non iList

5

je les méthodes d'extension suivantes:

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

Utilisation:

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

Très utile aussi bien lors du passage des valeurs directement:

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

Il est utile, mais il ne peut pas être traduit en expression magasin. –

+0

@MarekBar Vous pouvez toujours utiliser .AsEnumerable() avant le Where() .. – JoanComasFdz

+0

C'est vrai, mais je voudrais exécuter dans la base de données. AsEnumerable chargera les données dans la mémoire. –

0

Je l'ai créé d'une manière plus similaire à SQL, je pense qu'il est plus facile de comprendre

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();