2015-06-12 18 views
7

Ho uno scenario in cui desidero solo utilizzare la clausola WHERE quando è necessaria, altrimenti voglio solo eseguire la mia query LINQ senza la clausola WHERE.Come posso creare una clausola where condizionale usando LINQ

Ad esempio:

se string name = "";

var res = (from a in db.person 
      select new() { Name = a.FullName, DOB = a.DOB }).ToList(); 

se stringa nome = "satya";

var res = (from a in db.person 
      where a.person.contains(name) 
      select new() { Name = a.FullName, DOB = a.DOB }).ToList(); 

So che per questo dobbiamo scrivere separata 2 domande separatamente, ma senza scrivere query separate, come possiamo riunire in una singola query?

+1

Che '.toList()' dovrebbe essere '.ToList()'. Ma poi di nuovo, a meno che tu non abbia effettivamente bisogno di una lista, forse non dovrebbe esserci affatto; enumerare direttamente esclude la creazione di un elenco solo per poi enumerarlo. –

risposta

16

Si può fare:

var res = (from a in db.person 
      where name == "" || a.person.Contains(name) 
      select new { Name = a.FullName, DOB = a.DOB } 
     ).ToList(); 

In alternativa, qui utilizzando la sintassi fluente, si può costruire la query ed eseguirlo una volta che il gioco è fatto:

var query = db.person.AsQueryable(); 

if(!String.IsNullOrEmpty(name)) { 
    query = query.Where(a => a.person.Contains(name)); 
} 

var result = query.Select(s => new { Name = s.FullName, DOB = s.DOB }) 
        .ToList(); 
+0

Grazie per il commento, ma sto ricevendo Time Out Exception quando sto usando ToList(), dal momento che sta avendo alcuni record crores. Mentre sto recuperando i record, sto ricevendo un'eccezione, ma non ho ottenuto quell'eccezione se scrivo Query direttamente usando altre query separate. –

+0

Il timeout si verifica a causa del timeout in connessione che mantiene la connessione in tempo reale al database, poiché si sta tentando di recuperare il tipo IQueryable, l'opzione potrebbe aumentare il timeout della connessione, che è di default 60 sec o portare i dati in memoria ed elaborarli , che è quello che stai facendo nei tuoi loop se. Ad ogni modo l'elaborazione di questi dati per chiamata è pazzesca. –

0

Penso che si possa utilizzare il codice snippet 2 per ottenere lo stesso risultato con lo snippet di codice 1 anche il nome contiene una stringa vuota. Perché dovresti fare 2 codici diversi. È per problemi di prestazioni?

var res = (from a in db.person 
where a.person.contains(name) // if empty, it will return all list, just makes sure it's not null before 
select new(){Name=a.FullName,DOB=a.DOB}).toList(); 

provo questo nel mio codice di esempio ed è lavorare bene

static void TestContains() 
     { 
      IList<CustomEntity> _a = new List<CustomEntity>(); 
      IList<CustomEntity> _b = new List<CustomEntity>(); 

      _a.Add(new CustomEntity { ID = 1, Code = "a", Description = "aaa" }); 
      _a.Add(new CustomEntity { ID = 2, Code = "c", Description = "c" }); 

      string name = string.Empty; 
      _b = _a.Where(a => a.Description.Contains(name)).ToList(); 

      foreach (CustomEntity temp in _b) 
      { 
       Console.WriteLine(temp.Description); 
      } 
     } 

Questo sarà il risultato

aaa 
c 
+0

Ho provato questo nel mio codice di esempio e funziona bene. Intendi "" come vuoto, non 'nullo' giusto –

1

seguente dovrebbe funzionare, è possibile modificare il modo che ti piace raggiungere il risultato desiderato. Solo provvedendo condizione di stringa vuota/nullo o il nome è contenuta nel a.person, riposare tutta porterà a nullo, che filtriamo alla fine

db.person.Select(a=>{ 
        if (String.IsEmptyOrNull(name) || 
          a.person.contains(name)) 
         return new {Name=a.FullName,DOB=a.DOB}; 
         else 
         return null; 
        } 
       ).Where(x=>x!=null).ToList() 

ha creata su un blocco di testo, ci potrebbe essere piccola problema di sintassi