Entity Framework - "All" -Methode

entity-framework linq linq-to-entities

Frage

Die All- Methode soll das Argument gegen alle Elemente in der Liste auswerten. Es funktioniert in regulärem Linq in Ordnung, aber wenn ich versuche, es mit EF zu verwenden, wird ein Fehler ausgegeben (" Konstanter Wert des Typs 'Verschlusstyp' kann nicht erstellt werden. Es werden nur primitive Typen (zum Beispiel Int32, String und Guid) unterstützt Kontext. ")

Beispiel:

var myList = from person in entities.People
             where searchList.All(arg => arg == arg).ToList();

(arg == arg hier dient nur zur Veranschaulichung meiner Frage)

In meinem Szenario ist searchList eine Liste mit Suchelementen wie "John", "Accounting", "75". In meiner EF-Abfrage möchte ich alle Datensätze in Personen abrufen, für die John, Accounting und 75 in bestimmten angegebenen durchsuchbaren Feldern angezeigt werden. Ein realistischeres Beispiel wäre etwa so:

where SearchList.All((person.FirstName + " " + person.LastName + " " + person.DepartmentName + " " + person.Phone).Contains)

Das zweite Beispiel funktioniert auch gut mit Linq im Speicher, aber EF gefällt es nicht.

Bitte helfen Was kann ich tun, damit es funktioniert?

Dies ist eine spezifischere Frage, die aus einer anderen meiner Frage stammt.

Beispielcode:

IEnumerable<string> searchList = ParseSearchText(searchText); //search text is broken into search tokens - each token is an element in searchList. For instance "John", "Sales", "654"

var peopleQuery = from person in entities.vSearchPeople
where upperSearchList.All((person.FirstName + " " + person.Lastname + " " + person.Phone).ToUpperInvariant().Contains)
select person;

Akzeptierte Antwort

Das Entity Framework unterstützt nicht alle Abfragen. Dies wird offensichtlich, wenn Sie an Folgendes denken

dataContext.Persons.Where(person => MyMethod(person));

wobei MyMethod() einen booleschen Wert MyMethod() . Die Methode kann alles tun und Sie können nicht alles in SQL übersetzen. Die Lösung besteht darin, alle Entitäten mit ToList() in den lokalen Speicher zu ToList() und dann LINQ to Object zu verwenden.

dataContext.Persons.ToList().Where(person => MyMethod(person));

Es hängt von Ihrer tatsächlichen Abfrage ab, ob sie umgeschrieben werden kann, sodass sie vom Entity Framework in SQL umgewandelt werden kann, oder ob Sie die Abfrage im lokalen Speicher mit LINQ to Object durchführen müssen.

Die von Ihnen erwähnte Ausnahme klingt so, als würden Sie etwas wie das Folgende versuchen.

Company company = datacontext.Companies.Where(company.Name == "ACME").Single();

dataContext.Employees.Where(employee => employee.Company == company);

LINQ to Entity unterstützt keine Ausdrücke, die Entitäten enthalten. Daher ist der Vergleich der Entitäten der Company nicht gültig. In diesem Fall können Sie es wie folgt umschreiben.

dataContext.Employees.Where(employee => employee.Company.Id == company.Id);

Dies vergleicht nur die IDs - einen primitiven Typ wie eine Ganzzahl oder eine GUID - und dies kann in SQL umgewandelt werden.

Beispiel für die Suche Wort für Wort (siehe auch die Kommentare)

IQueryable<People> result = entities.People;

foreach (String item in searchList)
{
    // This copy is important in order not to modify the closure.
    String itemCopy = item;

    result = result.Where(p =>
        p.FirstName.ToUpper().Contains(itemCopy) ||
        p.LastName.ToUpper().Contains(itemCopy) ||
        p.Phone.ToUpper().Contains(itemCopy));
}

Dadurch wird die Abfrage Wort für Wort erstellt. Beachten Sie, dass das Entity Framework ToUpper() , ToLower() und Contains() (und einige mehr) erkennt - daher war ich zu streng, als ich sagte, dass das Entity Framework keine Methodenaufrufe erkennt. Es tut, aber nicht viele und nicht ToUpperInvariant() und ToLowerInvariant() . Außerdem wird diese Abfrage in CHARINDEX() -Funktionsaufrufe übersetzt, wobei die Sortierung der Spalte verwendet wird. Daher kann die Suche ohne explizite ToUpper() oder ToLower() Aufrufe zwischen Groß- und Kleinschreibung unterscheiden.


Beliebte Antwort

Dieses gute Beispiel zeigt, wie gut die All () - Methode funktioniert.

model.ReferenceList = db.JournalCardReference.OrderBy(a => a.orderF)
 .Include(x => x.JournalCardField)
  .Where(x => x.JournalCardField
    .All(f => f.deleted == null || f.deleted != true)).ToList();


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