2012-03-30 20 views
5

Ich habe Code wie folgt vor:Entity Framework generic

switch(sort.Column) 
{ 
    case "code": 
    model = (sort.Direction == SortDirection.Ascending) 
      ? model.OrderBy(x => x.code) 
      : model.OrderByDescending(x => x.code); 
    break; 
    case "name": 
    model = (sort.Direction == SortDirection.Ascending) 
      ? model.OrderBy(x => x.name) 
      : model.OrderByDescending(x => x.name); 
    break; 
.............. 
} 

Ich habe etwa 10 bis 15 Felder (wie ‚Code‘ und ‚Name‘) und ich möchte nicht einen ähnlichen Code mit nur einem kopieren und einfügen Differenz - Feldname.

Gibt es eine Methode, um die Abfrage irgendwie zu verallgemeinern?

+0

Sie wissen, was lustig ist? Wir haben diesen genauen Code in einer SortHelper-Klasse, die etwa 200 Mal eingefügt wurde: |. Interessiert zu sehen, was damit passiert! +1 – mattytommo

Antwort

7

Sie können mit Reflexion (unter Annahme code und name sind Eigenschaften, wenn sie öffentliche Variablen sind, werden Sie entsprechend ändern müssen):

model = (sort.Direction == SortDirection.Ascending) 
    ? model.OrderBy(x => x.GetType() 
     .GetProperty(sort.Column).GetValue(x, null)) : 
    : model.OrderByDescending(x => x.GetType() 
     .GetProperty(sort.Column).GetValue(x, null)); 

Wie In den folgenden Kommentaren weist Dunc darauf hin, dass dieser Ansatz die Reflexion bei jedem Schritt der Aufzählung erzwingt, und die Reflektion ist im Verlauf der Operationen teuer. Wenn Ihre Sammlung homogen ist, können Sie eine bessere Leistung erzielen, indem Sie die Reflexion aus der Aufzählung entfernen. Wenn Ihr model enthält nur Elemente vom Typ Foo, können Sie die folgenden stattdessen tun:

var prop = typeof(Foo).GetProperty(sort.Column); 

model = (sort.Direction == SortDirection.Ascending) 
    ? model.OrderBy(x => prop.GetValue(x, null)) : 
    : model.OrderByDescending(x => prop.GetValue(x, null)); 

Bitte nicht, dass dies eine TargetException werfen, wenn Sie Ihre Sammlung nicht homogen ist.

+0

Netter, kleiner Leistungsvorschlag: versuche, x.GetType(). GetProperty (sort.Column) aus dem LINQ-Ausdruck heraus zu bewegen, um wiederholte Reflexion zu vermeiden – Dunc

+0

Guter Vorschlag, Dunc, ich werde meine Antwort entsprechend aktualisieren. –

3

Dies würde Ihnen den Anfang machen, aber Sie könnten auch reflection verwenden, um den Eigenschaftennamen über die Spalte zu erhalten, wenn die Eigenschaft und die Spalte genau übereinstimmen.

model = Order(x => x.name); 

Aber mit Reflexion, können Sie es ohne den Schalter tun könnte, aber ich bin ein wenig auf Reflexion schwach, also werde ich es verlassen:

// inline function 
Func<Func<Model, TResult>, Model> Order = criteria => 
{ 
    return (sort.Direction == SortDirection.Ascending) 
      ? model.OrderBy(criteria) 
      : model.OrderByDescending(criteria); 
} 

... code down to switch ... 

Dies würde Ihren Namen Fall verkürzen an jemand anderen, wenn sie wollen.

1

Wie 'No So IP' sagt, gibt es Muster dafür - Befehl Dispatcher/Factory-Methode/etc. Das sind gültige Entscheidungen. Aber manchmal können diese einfach die Komplexität verbergen. Mein Vorschlag ist, mit dynamischer linq zu betrachten. Hier ist ein Link, um loszulegen: http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx

Sie können auch Ihre eigenen rollen, wenn Sie es wünschen, da es nicht übermäßig kompliziert ist. Erstellen Sie eigene Erweiterungsmethoden, mit denen Sie Parameter (z. B. Sortierrichtung, Sortierspalte) zu Ihrer Bestellung übergeben können. Erstellen Sie innerhalb dieser Erweiterungsmethode Ihre eigene Bestellung mit Hilfe der Anweisung unter Verwendung des Namespaces system.linq.expressions. Hier ist ein Beispiel dafür, wie gut: http://ronniediaz.com/2011/05/24/orderby-string-in-linq-c-net-dynamic-sorting-of-anonymous-types/

+0

Schöne Lösung, sieht wie zerlegt C# Quelle von LINQ-Abfragen aus. –