2008-12-30 4 views
7

Ich habe eine Linq to Entities wie diese Abfrage:Linq gibt Liste oder einzelnes Objekt

var results = from r in entities.MachineRevision 
       where r.Machine.IdMachine == pIdMachine 
       && r.Category == (int)pCategory 
       select r; 

Normalerweise verwende ich den Code unten zu überprüfen, ob einige Ergebnisse zurückgegeben werden:

if (results.Count() > 0) 
{ 
    return new oMachineRevision(results.First().IdMachineRevision); 
} 

jedoch Ich bekomme NotSupportedException im wenn Zustand.

Die Fehlermeldung lautet: Es konnte kein konstanter Wert vom Typ 'Schließungstyp' erstellt werden. Nur primitive Typen ('wie Int32, String und Guid') werden in diesem Kontext unterstützt.

Beachten Sie, dass pCategory ein Enum-Typ ist.

Antwort

11

BEARBEITEN: Basierend auf Ihrer Aktualisierung kann der Fehler mit einer Enumeration in Ihrer Entitätsklasse zusammenhängen. Weitere Informationen und eine Problemumgehung finden Sie unter blog entry. Ich überlasse meine ursprüngliche Antwort als Verbesserung Ihrer Abfragesyntax.

Versuchen Sie, die erste Entität in der Abfrage selbst mithilfe von FirstOrDefault auszuwählen, und überprüfen Sie dann, ob das Ergebnis null ist.

int compareCategory = (int)pCategory; // just a guess 
var result = (from r in entities.MachineRevision 
       where r.Machine.IdMachine == pIdMachine 
       && r.Category == compareCategory 
       select r).FirstOrDefault(); 

if (result != null) 
{ 
    return new oMachineRevision(result.IdMachineRevision); 
} 
+0

Immer noch nicht funktioniert, weil wir versuchen, die FirstOrDefault() auszuführen Methode für ein Entitätsobjekt (das ist, was von der linq-Anweisung zurückgegeben wird) und kein IEnumerable –

+1

Auswahl gibt immer ein IEnumerable zurück, siehe Dokumentation hier http://msdn.microsoft.com/en-us/library/bb548891.aspx. Bist du sicher, t Hat das Beispiel genau das gleiche wie dein Code? – tvanfosson

+0

Mein Fehler, ich entschuldige mich dafür. Um den Code zu vereinfachen, habe ich ein enum entfernt, genau wie tvanfosson durch die Fehlermeldung, die ich bekam, bemerkt wurde. Danke an alle und tut mir leid, dass ich dich irregeführt habe. –

0

versuchen

IENumerable<MachineRevision> results = from r in entities.MachineRevision 
... 

stattdessen verwenden.

Ich denke, es ist die Var, die Ihr Problem verursacht.

+0

Ich hatte bereits versucht, und das Ergebnis ist das gleiche :-( –

2

Warum nicht einfach FirstOrDefault() verwenden und auf Null prüfen? Ich kann den Vorteil nicht sehen, wenn ich nach der Zählung frage und dann das erste Element nehme.

+0

ich Ihren Punkt sehen kann. Wenn ich jedoch FirstOrDefault() verwenden, ich bin immer noch immer Diese NotSupportedException, weil ich versuche, diese Methode auf einem Entitätsobjekt (das ist, was von der Linq-Anweisung zurückgegeben wird), nicht auf einem IEnumerable. –

0

Edit:

Lesen Sie die Fehlermeldung. "Es ist nicht möglich, einen konstanten Wert vom Typ 'Closure type' zu erstellen. Nur primitive Typen ('wie Int32, String und Guid') werden in diesem Kontext unterstützt."

Einer dieser Vergleiche ist mit einem Typ, der nicht Int, String oder GUID ist. Ich schätze die Kategorie.

r.Machine.IdMachine == pIdMachine && r.Category == pCategory 

Interessanterweise wird LinqToSql diese Konstruktion erlauben. Ich weiß nicht, warum LinqToEntities dies nicht unterstützt.

1

Ich wusste nicht, dass verschiedene anonyme Objekte abhängig vom Abfrageergebnis erstellt werden würden. Ich denke, sie wollten nur Ergebnisse vom Typ IEnumerable

Wie wäre es mit einer Foreach?

var results = from r in entities.MachineRevision 
       where r.Machine.IdMachine == pIdMachine 
       && r.Category == pCategory 
       select r; 

foreach(var r in results) 
{ 
    yield return new oMachineRevision(r.IdMachineRevision); 
} 
2

In der Standardimplementierung von Linq, die Operatoren „wählen“ und „wo“ Methoden zuordnen, die ein IEnumerable oder IQueryable zurückgeben. Daher sollten Standard-Linq-Methoden, wenn sie verwendet werden, immer ein IEnumerable aus Ihrer Abfrage nicht ein einzelnes Objekt zurückgeben.

Aber Linq-Methoden, die Kandidaten für die Linq-Operatoren sind, sind nicht auf Methoden beschränkt, die IEnumerables zurückgeben, jede Methode, die irgendetwas zurückgibt, kann gewählt werden.

Wenn Sie die Instanzmethoden "Select" und "Where" haben, die ein einzelnes Objekt oder spezifische Extension-Methoden zurückgeben und ein einzelnes Objekt zurückgeben, werden diese anstelle der Standard-Linq-Objekte verwendet.

Meine Vermutung ist, dass entweder eine "Select" - oder "Where" -Methode, die in Ihrer Klasse definiert ist, linq einen einzelnen Wert anstelle von IEnumerable<T> zurückgibt.

0

Ich denke, Sie könnten auch das Element, das Sie wollen, einen anderen, einfacheren Weg mit Lambda-Ausdrücke wählen.

var result = entities.MachineRevision 
       .Where(x => x.Machine.IdMachine == pIdMachine) 
       .Where(y => y.Category == (int)pCategory) 
       .FirstOrDefault(); 

if (result != null) 
{ 
    return new oMachineRevision(result.IdMachineRevision); 
} 

und verläuft dann, wie man es normalerweise

+1

Funktioniert nicht, weil die ".Where (y => y.Category == (int) pCategory)" einen Fehler erzeugt. Sie müssen die Umwandlung von Enum vor der Abfrage durchführen. var iCategory = (int) pKategorie; und dann einfach die iCategory in der Abfrage selbst verwenden. – derSteve

1

Auch dies für alle impliziten Typen geht. Ich muss zugeben, dass ich das immer wieder vergesse und so bin ich auf diesen Posten gestoßen.

wenn Sie

class ClassA { 
       ... 

       private string value; 

       ... 

       public static implicit operator string(ClassA value) 
       { 
        return value.ToString(); 
       } 

       ... 
} 

haben müssen Sie explizit die Klasse astring zum Vergleich zu werfen.

so ich in der Regel tun dies

var myClassAStr = myClassA.ToString(); 

    var x = (from a in entites where a.ValToCompare == myClassAStr select a).first(); 

// do stuff with x 
    ... 
+0

tatsächlich verwende ich normalerweise a.ValToCompare.Equals (myClassAstr) –