2015-06-20 8 views
5

Nel mio codice C#, ho bisogno di valutare due variabili non nulle. Ho elaborato un set di if-else if dichiarazioni, ma nella mia mente sembra brutto e un po 'troppo sciatto, anche se è corretto.Esiste un modo efficace per eseguire una dichiarazione di selezione con due variabili?

Ho guardato nello MSDN Library e ho visto solo esempi di selezione basati su una singola variabile.

C'è un modo più pulito e più compatto per ottenere lo stesso risultato?

Aggiornamento: Ho inserito il codice per fornire più contesto. Guardando di più, forse posso manipolare la query di linq direttamente in base ai parametri. Tuttavia, la domanda che pongo è quella generica su cui vorrei concentrarmi: la selezione anziché il codice utilizzato dopo la selezione.

public ActionResult Index(string searchBy, string orderBy, string orderDir) 
{ 
    var query = fca.GetResultsByFilter(searchBy); 

    if (orderBy == "Campus" && orderDir == "Asc") 
    { 
     query = query = query.OrderBy(s => s.Campus).ThenBy(s => s.Student_Name); 
    } 
    else if (orderBy == "Campus" && orderDir == "Desc") 
    { 
    query = query.OrderByDescending(s => s.Campus); 
    } 
    else if (orderBy == "Student Name" && orderDir == "Asc") 
    { 
     query = query = query.OrderBy(s => s.Student_Name); 
    } 
    else if (orderBy == "Student Name" && orderDir == "Desc") 
    { 
     query = query.OrderByDescending(s => s.Student_Name); 
    } 
    else if (orderBy == "Course Count" && orderDir == "Asc") 
    { 
    query = query.OrderBy(s => s.Course_Count); 
    } 
    else if (orderBy == "Course Count" && orderDir == "Desc") 
    { 
    query = query.OrderByDescending(s => s.Course_Count); 
    } 
} 
+1

Qual è il codice '/ * ... * /'? È possibile utilizzare LINQ per eseguire query come questa, assumendo che ciò che si trova all'interno del codice. – Cyral

+0

Stavo parlando in un senso più generico. Questi sono i parametri inviati alla funzione da un modulo di invio. Modificheremo la mia domanda postata per fornire quel contesto. –

+0

Si potrebbe dapprima creare un metodo come If (controllare ("campus", "ASC")) ..., quindi aggiungere le stringhe in un array e scorrere tra ... per (i ...) {if (controllare (strby [i], strdir [i]))} .... o crea un oggetto speciale per esso se non ti piacciono due array ... – ElDuderino

risposta

4

È possibile creare un metodo di estensione su IQueryable che gestisce l'ordinazione sia con OrderBy o OrderByDescending:

public static class QueryableExtensions 
{ 
    public static IOrderedQueryable<TSource> OrderByWithDirection<TSource,TKey> 
     (this IQueryable<TSource> source, 
     Expression<Func<TSource, TKey>> keySelector, 
     string orderDir) 
    { 
     return orderDir == "Desc" 
         ? source.OrderByDescending(keySelector) 
         : source.OrderBy(keySelector); 
    } 
} 

sto supponendo che il metodo GetResultsByFilter restituisce un IQueryable<>. Se restituisce effettivamente un valore IEnumerable<>, il metodo di estensione richiederà un parametro IEnumerable<TSource> source e restituirà invece un valore IOrderedEnumerable<TSource>.

Questo può quindi essere utilizzati nel modo seguente:

public ActionResult Index(string searchBy, string orderBy, string orderDir) 
{ 
    var query = fca.GetResultsByFilter(searchBy); 

    switch (orderBy) 
    { 
     case "Campus": 
      query = query.OrderByWithDirection(s => s.Campus, orderDir); 
      break; 
     case "Student Name": 
      query = query.OrderByWithDirection(s => s.Student_Name, orderDir); 
      break; 
     case "Course Count": 
      query = query.OrderByWithDirection(s => s.Course_Count, orderDir); 
      break; 
    } 

    if (orderBy == "Campus" && orderDir == "Asc") 
    { 
     // The Campus Asc case was also ordered by Student_Name in the question. 
     query = query.ThenBy(s => s.Student_Name); 
    } 
} 
+0

Buona domanda GetResultsByFilter (stringa) chiama 'IEnumerable GetResultsByFilter (filtro stringa)'. Consiglieresti di metterlo nel modello o nel controller? –

+0

@Rubix_Revenge Supponendo che questa sia una query di database, sarebbe meglio rendere 'GetResultsByFilter' return' IQueryable '. Ciò consentirà l'esecuzione di 'OrderBy' a livello di database come SQL 'ORDER BY' (consultare http://stackoverflow.com/q/2876616). Probabilmente avrei inserito il metodo 'GetResultsByFilter' nel controller a meno che non fosse usato in più di un controller. –

+0

Ho creato IEnumerable per funzionare con le maggiori esigenze della vista MVC. Hai sollevato un buon punto, ma ora sto rientrando nel mondo di whack-a-mole, dove apportare un cambiamento causa problemi in altri posti. –

1

Vorrei utilizzare l'operatore terniario per renderlo più compatto e più facile da leggere in questo modo.

In questo modo si eliminano anche alcuni controlli booleani poiché non ne duplica nessuno.

public ActionResult Index(string searchBy, string orderBy, string orderDir) 
    { 
     var query = fca.GetResultsByFilter(searchBy); 

     if (orderBy == "Campus") 
     { 
      query = (orderDir == "Asc") ? query.OrderBy(s => s.Campus).ThenBy(s => s.Student_Name) : 
       query.OrderByDescending(s => s.Campus); 
     } 
     else if (orderBy == "Student Name") 
     { 
      query = (orderDir == "Asc") ? query.OrderBy(s => s.Student_Name) : query.OrderByDescending(s => s.Student_Name); 
     } 
     else if (orderBy == "Course Count") 
     { 
      query = (orderDir == "Asc") ? query.OrderBy(s => s.Student_Name) : query.OrderByDescending(s => s.Course_Count); 
     } 
    } 
+0

Non ho pensato ad un operatore ternario, ma mi piace . È facile da leggere e creare e posso vedere facilmente come funziona ora che lo vedo. –

+0

Felice di aiutare. Sono molto utili. – deathismyfriend

2

CNot sicuro se questo è meglio, solo diverso.

switch (orderDir) 
{ 
    case "Asc": 
     Switch (orderBy) 
     { 
      case "Campus": 
       //Code here for Campus orderBy and Asc orderDir 
       break; 
      case "Student Name": 
       //Code here for Student Name orderBy and Asc orderDir 
       break; 
      case "Course Count": 
       //Code here for Course Count orderBy and Asc orderDir 
       break; 
     } 
     break; 
    case "Desc": 
     Switch (orderBy) 
     { 
      case "Campus": 
       //Code here for Campus orderBy and Desc orderDir 
       break; 
      case "Student Name": 
       //Code here for Student Name orderBy and Desc orderDir 
       break; 
      case "Course Count": 
       //Code here for Course Count orderBy and Desc orderDir 
       break; 
     } 
     break; 
} 
0

mio prendere:

public interface IOrder { 
    void perform(Query query) 
} 

public abstract class AbstractOrder : IOrder { 

    protected string orderString; 

    public AbstractOrder(string orderString) { 
     this.orderString = orderString; 
    } 
} 

public class OrderAsc { 

    public OrderAsc(string orderString) : base(orderString) { 
    } 

    public Query perform(Query query) { 
     query = query.OrderBy(s => s.Course_Count); //here you still have to do a mapping between orderString and your db field s.Course_count 
     return query; 
    } 
} 

public class OrderDesc { 

    public OrderDesc(string orderString) : base(orderString) { 
    } 

    public Query perform(Query query) { 
     query = query.OrderByDescending(s => s.Course_Count); //here you still have to do a mapping between orderString and your db field s.Course_count, or maybe it's equal, then you can just replace it. 
     return query; 
    } 
} 

poi ...

IList<IOrder> list = new List<IOrder>() {new OrderAsc("Campus"), new OrderDesc("Student Name")} 

foreach(IOrder o in list) { 
    query = o.perform(query); 
} 

Ci potrebbero essere alcuni errori in esso, io don avere un IDE a portata di mano.

+0

Dato che sono ancora sulla curva dell'apprendimento linguistico, questo è sicuramente nuovo per me. Ma questo mi dà più materiale da masticare. Grazie –

Problemi correlati