Entity Framework - Fehler beim Erstellen eines konstanten Werts vom Typ 'Verschlusstyp' ... "

entity-framework linq

Frage

Warum erhalte ich die Fehlermeldung:

Konstanter Wert des Typs 'Verschlusstyp' kann nicht erstellt werden. In diesem Zusammenhang werden nur primitive Typen (z. B. Int32, String und Guid) unterstützt.

Wenn ich versuche, die folgende Linq-Abfrage aufzulisten?

IEnumerable<string> searchList = GetSearchList();
using (HREntities entities = new HREntities())
{
   var myList = from person in entities.vSearchPeople
   where upperSearchList.All( (person.FirstName + person.LastName) .Contains).ToList();
}

Update : Wenn ich nur versuche, das Problem zu isolieren, erhalte ich die gleiche Fehlermeldung:

where upperSearchList.All(arg => arg == arg) 

Es sieht also so aus, als ob das Problem bei der All-Methode liegt, oder? Irgendwelche Vorschläge?

Akzeptierte Antwort

Es sieht so aus, als würden Sie versuchen, das Äquivalent einer "WHERE ... IN" Bedingung zu tun. Ein Beispiel dafür, wie diese Art von Abfragen mit LINQ to Entities durchgeführt wird, finden Sie unter So schreiben Sie Abfragen im WHERE-Stil mit LINQ to Entities.

Ich denke auch, dass die Fehlermeldung in diesem Fall besonders wenig hilfreich ist, da auf .Contains keine Klammern folgen, wodurch der Compiler das gesamte Prädikat als Lambda-Ausdruck erkennt.


Beliebte Antwort

Ich habe die letzten 6 Monate damit verbracht, mit EF 3.5 gegen diese Einschränkung zu kämpfen. Ich bin zwar nicht die klügste Person der Welt, aber ich bin mir ziemlich sicher, dass ich zu diesem Thema etwas Nützliches anbieten kann.

Die durch das Wachsen eines 50 Meilen hohen Baums mit "OR-Stil" -Ausdrücken generierte SQL führt zu einem schlechten Ausführungsplan für Abfragen. Ich habe ein paar Millionen Zeilen und die Auswirkungen sind erheblich.

Es gibt einen kleinen Hacker, den ich gefunden habe, um eine SQL 'in' zu erstellen, die hilft, wenn Sie nur nach einer Reihe von Entitäten nach ID suchen:

private IEnumerable<Entity1> getByIds(IEnumerable<int> ids)
{
    string idList = string.Join(",", ids.ToList().ConvertAll<string>(id => id.ToString()).ToArray());
    return dbContext.Entity1.Where("it.pkIDColumn IN {" + idList + "}");
}

Dabei ist pkIDColumn der Name der Primärschlüssel-ID Ihrer Entity1-Tabelle.

ABER LESEN SIE NICHT!

Das ist in Ordnung, aber es erfordert, dass ich bereits die IDs von dem habe, was ich finden muss. Manchmal möchte ich nur, dass meine Ausdrücke in andere Beziehungen hineinreichen, und was ich habe, sind Kriterien für diese verbundenen Beziehungen.

Wenn ich mehr Zeit hätte, würde ich versuchen, dies visuell darzustellen, aber ich studiere diesen Satz nicht für einen Moment: Betrachten Sie ein Schema mit den Tabellen "Person", "GovernmentId" und "GovernmentIdType". Andrew Tappert (Person) hat zwei Ausweise (GovernmentId), einen aus Oregon (GovernmentIdType) und einen aus Washington (GovernmentIdType).

Erzeugen Sie jetzt einen edmx daraus.

Stellen Sie sich vor, Sie möchten alle Personen mit einem bestimmten ID-Wert finden, z. B. 1234567.

Dies kann mit einem einzigen Datenbankhit erreicht werden:

dbContext context = new dbContext();
string idValue = "1234567";
Expression<Func<Person,bool>> expr =
    person => person.GovernmentID.Any(gid => gid.gi_value.Contains(idValue));

IEnumerable<Person> people = context.Person.AsQueryable().Where(expr);

Sehen Sie die Unterabfrage hier? Das generierte SQL verwendet 'Joins' anstelle von Unterabfragen, der Effekt ist jedoch derselbe. Heutzutage optimiert SQL Server Unterabfragen sowieso in Verknüpfungen, aber trotzdem ...

Der Schlüssel zu dieser Funktion ist die .Any im Ausdruck.



Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum
Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum