2011-01-17 14 views
2

Ich verwende LINQ to SQL für eine .NET MVC-Anwendung.Übergeben Sie den Namen der Eigenschaft als String in die Methode .NET.

In meinem db habe ich eine Reihe von Spalten, die "Y" oder "N" -Werte in ihnen haben.

Ich versuche, ein Allzweck-Methode zu schreiben, die alle Datensätze in der db zurück, wo columnName == 'Y'

Bisher habe ich diese

public IQueryable<Approved> ReturnRecordsByObjectiveFlag(string columnName) 
{  
    return from approved in db.Approved 
      where approved.GetType().GetProperties().Where(x => x.Name.Equals(columnName)).Equals("Y") 
      select approved; 
} 

Aber das gibt mir diesen Fehler haben

Member access 'System.String Name' of 'System.Reflection.MemberInfo' not legal on type 'System.Reflection.PropertyInfo[].

Irgendeine Idee, wo ich vielleicht falsch liege?

Vielen Dank.

+0

Was die Art der 'approved' ist? – abatishchev

+0

Nicht feste und möglicherweise große Mengen von Spaltennamen. Es ist Enterprisey. – MrBliz

+0

Die Reflektion funktioniert nicht unter Linq2SQL. Sie müssen einen Ausdruck konstruieren. – leppie

Antwort

3
public IQueryable<Approved> ReturnRecordsByObjectiveFlag(string columnName) 
{ 
    var param = Expression.Parameter(typeof(Approved), "x"); 
    var predicate = Expression.Lambda<Func<Approved,bool>>(
     Expression.Equal(
      Expression.PropertyOrField(param, columnName), 
      Expression.Constant("Y") 
     ), param); 
    return db.Approved.Where(predicate); 
} 

bearbeiten; wenn die Eigenschaften char? sind tatsächlich, dh 'Y' nicht "Y", dann:

public IQueryable<Approved> ReturnRecordsByObjectiveFlag(string columnName) 
{ 
    var param = Expression.Parameter(typeof(Approved), "x"); 
    Expression prop; 
    var predicate = Expression.Lambda<Func<Approved, bool>>(
     Expression.Equal(
      (prop = Expression.PropertyOrField(param, columnName)), 
      Expression.Constant(prop.Type == typeof(string) ? 
       (object)"Y" : (object)'Y', prop.Type) 
     ), param); 
    return db.Approved.Where(predicate); 
} 

(diese meistert jetzt mit allen string, char und char?

+0

Danke Marc. Ich erhalte den Fehler System.InvalidOperationException: Der binäre Operator Equal ist nicht für die Typen 'System.Nullable'1 [System.Char]' und 'System.String' definiert. – MrBliz

+0

@ Doozer1979: Behebung entweder deine Frage oder behebe dein DB-Schema. – leppie

+0

@ Doozer1979: Versuchen Sie 'Expression.Constant ((char?) 'Y')' – leppie

1

Was schief läuft ist, dass Sie keine Reflektion in einer LINQ-Abfrage verwenden können.

Wie viele Spalten gibt es - ist es eine feste relativ kleine Zahl? Wenn dies der Fall ist, verwenden Sie eine switch-Anweisung, um zwischen einer Anzahl von LINQ-Abfragen zu wählen. Das ist sauberer und viel schneller.

Wenn es eine große Anzahl von Spalten ist, oder sie sind dynamisch, könnten Sie eine dynamische SQL-Anweisung, bauen aber vorsichtig sein, für mögliche Injection-Angriffe zu überprüfen.

+2

können Sie * eine LINQ-Abfrage erstellen, obwohl –

0
  • GetType() kehrt Type

  • GetProperties() kehrt PropertyInfo[]

  • Where(..) kehrt IEnumerable<PropertyInfo>

so nennt man

IEnumerable<PropertyInfo>.Equals(string) 

, die falsch zu sein scheint. Nicht wahr?

1
approved.GetType().GetProperties() 

wird ein PropertyInfo [] -Objekt zurückgeben. Selbst wenn Sie es mit einer Where filtern, ist es immer noch nicht der Wert der Eigenschaft, es ist im Grunde eine Sammlung von Eigenschaften, die die Kritik erfüllen, auch wenn diese Sammlung nur ein Mitglied hat.

Um eine bestimmte Eigenschaft von Namen zu erhalten, sollten Sie besser die GetProperty() Methode der Typ-Klasse verwenden, wie folgt aus:

PropertyInfo pi = approved.GetType().GetProperty(columnName); 

aber, du bist noch nicht fertig. Sie haben noch die Objekte durch den Wert der Immobilie zu filtern, und das wird unter Verwendung der GetValue() Methode auf dem Grundstück, wie dies getan:

bool isApproved = pi.GetValue(approved, null).Equals("Y"); 

oder alles in Ihrem Kontext zu setzen:

return from approved in db.Approved 
where approved.GetType().GetProperty(columnName) 
        .GetValue(approved, null).Equals("Y") 
select approved; 
+1

Warum ein Downwote? – SWeko

+0

War ich nicht, aber deine Antwort funktioniert nicht, wie bereits in vielen Kommentaren erwähnt. – leppie

+0

Ich habe auch nicht runtergestimmt. Es gibt mir den Fehler: Keine Überladung für die Methode 'GetValue' dauert '1' Argumente – MrBliz

-2

Das liegt daran, dass die letzte Equals-Methode in einer gefilterten IQueryable-Auflistung anstelle des Eigenschaftswerts selbst ausgeführt wird.

diese stattdessen versuchen:

return from approved in db.Approved 
       where approved.GetType().GetProperties().Where(x => x.Name.Equals(columnName) && (string)x.GetValue(db.Approved, null) == "Y") 
       select approved; 
+1

-1: Bitte lesen Sie die Kommentare/Antworten bereits gepostet, um zu verstehen, warum dies nicht funktioniert. – leppie

+0

Vielen Dank, dass Sie darauf hingewiesen haben. –

Verwandte Themen