2014-12-03 18 views
6

Ho un modulo con più criteri di ricerca che un utente può utilizzare per cercare i dati dei dipendenti, ad es. FirstName, LastName, HireDate, Department, ecc.Dichiarazione LINQ inaffidabile con più criteri di ricerca

Sto usando LINQ e mi sto chiedendo quale metodo potrei usare per interrogare una collezione di Employes dato uno qualsiasi dei criteri di ricerca, cioè un utente non deve inserire tutto, ma devono inserire almeno uno dei parametri di ricerca.

Finora, durante il test della mia istruzione LINQ con due parametri di ricerca in atto, sembra che devo vedere se il parametro di ricerca è inserito o meno. Se questo è il caso, allora questo può diventare abbastanza ingombrante per molti parametri di ricerca.

// only FirstName is entered 
if (!string.IsNullOrEmpty(FirstName) && string.IsNullOrEmpty(LastName)) 
{ 
    var employees = DB.Employees 
     .Where(emp => emp.FirstName.Contains(fName)); 
} 
// only LastName is entered 
else if (string.IsNullOrEmpty(FirstName) && !string.IsNullOrEmpty(LastName)) 
{ 
    var employees = DB.Employees 
     .Where(emp => emp.LastName.Contains(lName)); 
} 
// both parameters are entered 
else if (!string.IsNullOrEmpty(FirstName) && !string.IsNullOrEmpty(LastName)) 
{ 
    var employees = DB.Employees 
     .Where(emp => emp.FirstName.Contains(fName)) 
     .Where(emp => emp.LastName.Contains(lName)); 
} 

FYI, inizialmente ho pensato che avrei potuto basta aggiungere Dove() dichiarazioni alla mia dichiarazione LINQ con i parametri di ricerca pertinenti, ma ho notato che non tutti i record sono stati restituiti che dovrebbe e quindi la logica sopra di se: quindi affermazioni.

+0

È possibile aggiungere più istruzioni LINQ se si sta lavorando con un IQuery. È questo LINQ to Objects o stai usando un ORM per interrogare un database? – cost

+0

@cost - All'inizio, non ho capito il tuo suggerimento, ma dopo aver visto le risposte fornite, credo che tu abbia ragione. Grazie! –

risposta

6

Che dire qualcosa di simile:

IQueryable<Employee> employees = DB.Employees; 

if (!string.IsNullOrEmpty(FirstName)) 
{ 
    employees = employees 
     .Where(emp => emp.FirstName.Contains(fName)); 
} 
if (!string.IsNullOrEmpty(LastName)) 
{ 
    employees = employees 
     .Where(emp => emp.Last.Contains(lName)); 
} 
+0

Ahh! Se capisco la tua logica, ogni volta che passa una dichiarazione "se", l'IQueryable originale, i dipendenti, continua ad essere accodato con più istruzioni .Where(), corretto? –

+0

@frenu e 'IQueryable' è come un'istruzione LINQ non valutata. Finché non si itera la query (come con '.ToList()'), la query stessa non verrà eseguita.Quindi continuerai a costruire le tue clausole Where, e poi verranno valutate ed eseguite quando finalmente proverai a estrarre i dati. – cost

+0

@cost: Grazie per la spiegazione! –

4

si può scrivere in questo modo:

var employees = DB.Employees.AsQueryable(); 
if (!string.IsNullOrEmpty(fName) 
    employees = employees.Where(emp => emp.FirstName.Contains(fName)); 

if (!string.IsNullOrEmpty(lName) 
    employees = employees.Where(emp => emp.LastName.Contains(lName)); 
+0

Non è necessario dichiarare 'employee' esplicitamente come' IQueryable'? – cost

+0

@cost, sì proprio vero, grazie. – Magnus

1

ho incontrato una sfida simile in cui un utente potrebbe selezionare 0, 1 o più valori per circa 10 campi ricercabili e necessari per costruire quella query in fase di runtime.

ho finito per usare LINQKit: http://www.albahari.com/nutshell/linqkit.aspx

In particolare ho usato è builder predicato, che è descritto qui: http://www.albahari.com/nutshell/predicatebuilder.aspx

Nel tuo esempio sopra, hai abbracciato il multiplo query all'interno if . L'alternativa è costruire la query man mano che si procede.

Se si dovessero dichiarare dipendenti var = DB.Employees al di fuori di quelle if if (Supponendo che sia sempre pertinente), allora si potrebbe semplicemente applicare le istruzioni where nelle istruzioni if ​​se sono applicabili.

LINQ ti dà l'esecuzione differita, quindi non devi avere l'intera espressione in un unico blocco (anche se sembra più naturale farlo e in molti casi lo farai).

cose si fanno un po 'più complicato, se volete mescolare in OR di con AND, ma è lì che il costruttore predicato già citato entra in gioco.

Purtroppo non ho alcun esempio da condividere, ma questi collegamenti dovrebbero iniziare bene.

+0

Ho effettivamente il libro Albahari 5.0 e sono un cliente di LINQPad. Non avevo nemmeno pensato a LINQKit, ma qualcosa che sto esaminando in questo momento. Grazie! –

0
var resultData = (from data in db.Abc 
        where !string.IsNullOrEmpty(firstName) ? data.FirstName == firstName : true 
&& data.UserType == userTypeValue 
&& !string.IsNullOrEmpty(lastName) ? data.LastName == lastName : true 
&& !string.IsNullOrEmpty(gender) ? data.Gender == gender : true 
&& !string.IsNullOrEmpty(phone) ? data.CellPhone == phone : true 
&& !string.IsNullOrEmpty(fax) ? data.Fax == fax : true 
&& !string.IsNullOrEmpty(emailAddress) ? data.Email == emailAddress : true 
&& !string.IsNullOrEmpty(address1) ? data.Address == address1 : true 
           select new 
           { 
            UserName = data.UserName, 
            FirstName = data.FirstName, 
            Address = data.Address, 
            CellPhone = data.CellPhone, 
            Fax = data.Fax, 
            Email = data.Email 
           }).ToList(); 
+0

È possibile utilizzare questo codice, se si desidera cercare elementi in base a più condizioni di ricerca –

+0

Ciao Ramu, grazie per il vostro contributo. sarà meglio se aggiungi puntatori e commenti per spiegare perché questo codice funzionerà per risolvere questo problema. – NSNoob