2012-04-26 19 views
6

Uso EntityFramework con POCOs.
Supponiamo che io sono pocos definito come questo (semplificato):Query LINQ con una clausola WHERE con condizioni multiple

class Class1 
{ 
    public int ID; 
    public int SomeNumber; 
} 

class Class2 
{ 
    public int ID; 
    public int SomeNumber; 
} 

class Class3 
{ 
    public int ID; 
    public int SomeNumber; 
} 

class SomeClass 
{ 
    public int ID; 
    public int? Class1ID; 
    public Class1 Class1; 
    public int? Class2ID; 
    public Class2 Class2; 
    public int? Class3ID; 
    public Class3 Class3; 
} 

Voglio recuperare tutti SomeClass record del database, che appartengono a un uno di Class1, Class2 o Class3 dove ClassX.SomeNumber uguale qualche numero.

ho scritto la query LINQ che assomiglia a questo:

Database DB = new Database(); // object context 
var result = DB.SomeClass.ToList(); 

int SomeNumber = 1; // some number 
List<SomeClass> retValue = result 
    .Where(x => 
     { 
      int Number = 0; 
      if (x.Class1 != null) 
       Number = x.Class1.SomeNumber; 
      else if (x.Class2 != null) 
       Number = x.Class2.SomeNumber; 
      else if (x.Class3 != null) 
       Number = x.Class3.SomeNumber; 
      return Number == SomeNumber; 
     }) 
    .ToList(); 

... però retValue non contiene alcun record.

La soluzione

A quanto pare ho dovuto specificare .Include dichiarazioni perché lazy loading è stato disattivato e x.Class1, x.Class2 e x.Class3 aveva sempre il valore null. Mi vergogno perché non ho dichiarato esplicitamente che il caricamento pigro è stato disabilitato - il problema sarebbe stato ovvio allora.

Tuttavia, grazie al post di Ladislav, ho migliorato il mio codice in questo modo:

Database DB = new Database(); // object context 

int SomeNumber = 1; // some number 
List<SomeClass> retValue = DB.SomeClass 
    .Include("Class1") 
    .Include("Class2") 
    .Include("Class3") 
    .Where(x => 
     SomeNumber == x.Class1.SomeNumber || 
     SomeNumber == x.Class2.SomeNumber || 
     SomeNumber == x.Class3.SomeNumber) 
    .ToList(); 

non sapevo LINQ to Entities dovrebbero eseguire coalescenza automatica nullo.

risposta

3

IMHO si dovrebbe essere OK con solo questo:

Database DB = new Database(); 
var result = DB.SomeClass.Where(x => 
          Number == x.Class1.SomeNumber || 
          Number == x.Class2.SomeNumber || 
          Number == x.Class3.SomeNumber) 
         .ToList(); 

I suoi carichi di query tutti i dati e dopo che è valutare le condizioni in .NET = È necessario testare valore null prima di accedere SomeNumber, ma che non è necessaria se si valuta SomeNumber in SQL tramite le entità Linq. Linq-to-entities dovrebbe eseguire coal coal null automatico.

+0

In realtà la soluzione è stata (di solito trovo io stesso poco dopo chiedo) che a causa di caricamento pigro disabilitato , Dovevo fare 'var result = DB.SomeClass.Include (" Class1 "). Include (" Class2 "). Include (" Class3 ")' prima di eseguire la clausola 'Where'. Tuttavia sto segnalando questo come accettato perché mi hai insegnato come migliorare il mio codice (usa 'Where' in LINQ-To-Entities direttamente) –

2

Secondo la tua logica, se x.Class1 non è nullo, ma x.Class1.SomeNumber è 3, non controllerà tutte le altre clausole.

Se si desidera controllare, se solo alcuni ClassN.SomeNumber == SomeNumber, allora si dovrebbe fare in questo modo:

int SomeNumber = 1; // some number 
List<SomeClass> retValue = result 
    .Where(x => 
     { 
      if (x.Class1 != null && x.Class1.SomeNumber == SomeNumber) 
       return true; 
      else if (x.Class2 != null && x.Class2.SomeNumber == SomeNumber) 
       return true; 
      else if (x.Class3 != null && x.Class3.SomeNumber == SomeNumber) 
       return true; 
      return false; 
     }) 
    .ToList(); 
+0

Non è questo codice uguale a quello che ho usato, tranne il mio codice ha 1 altro linea? –

+0

No, poiché ritorna immediatamente se i numeri sono uguali. Nel tuo codice è possibile che esista un numero corretto, ma viene cancellato da un'altra clausola if. – LueTm

+0

Non può essere sovrascritto perché ci sono clausole 'else' e ​​restituisce 0 se nessuna delle condizioni corrisponde. –