Es gibt einen Entitätstyp namens Produkt, der vom Entitätsframework generiert wird. Ich habe diese Anfrage geschrieben
public IQueryable<Product> GetProducts(int categoryID)
{
return from p in db.Products
where p.CategoryID== categoryID
select new Product { Name = p.Name};
}
Der folgende Code löst den folgenden Fehler aus:
"Die Entität oder der komplexe Typ Shop.Product kann nicht in einer LINQ to Entities-Abfrage erstellt werden."
var products = productRepository.GetProducts(1).Tolist();
Aber wenn ich select p
stattdessen benutze select new Product { Name = p.Name};
, funktioniert es richtig.
Wie kann ich einen benutzerdefinierten Auswahlabschnitt erstellen?
c#
entity-framework
Ghooti Farangi
quelle
quelle
Antworten:
Sie können (und sollten) nicht auf eine zugeordnete Entität projizieren. Sie können jedoch auf einen anonymen Typ oder auf ein DTO projizieren :
Und Ihre Methode gibt eine Liste der DTOs zurück.
quelle
Sie können in einen anonymen Typ und dann in einen Modelltyp projizieren
Edit : Ich werde etwas genauer sein, da diese Frage viel Aufmerksamkeit bekommen hat.
Sie können nicht direkt in den Modelltyp projizieren (EF-Einschränkung), daher führt kein Weg daran vorbei. Die einzige Möglichkeit besteht darin, in einen anonymen Typ (1. Iteration) und dann in einen Modelltyp (2. Iteration) zu projizieren.
Beachten Sie auch, dass beim teilweisen Laden von Entitäten auf diese Weise diese nicht aktualisiert werden können. Daher sollten sie unverändert bleiben.
Ich habe nie ganz verstanden, warum dies nicht möglich ist, und die Antworten in diesem Thread geben keine starken Gründe dafür (meistens über teilweise geladene Daten). Es ist richtig, dass in einem teilweise geladenen Zustand die Entität nicht aktualisiert werden kann, diese Entität jedoch getrennt wird, sodass versehentliche Versuche, sie zu speichern, nicht möglich sind.
Betrachten Sie die oben verwendete Methode: Als Ergebnis haben wir immer noch eine teilweise geladene Modellentität. Diese Entität ist getrennt.
Betrachten Sie diesen (Wunsch zu existieren) möglichen Code:
Dies könnte auch zu einer Liste getrennter Entitäten führen, sodass wir keine zwei Iterationen durchführen müssten. Ein Compiler wäre schlau zu sehen, dass AsNoTracking () verwendet wurde, was zu getrennten Entitäten führt, sodass wir dies tun könnten. Wenn jedoch AsNoTracking () weggelassen wurde, könnte es dieselbe Ausnahme auslösen wie jetzt, um uns zu warnen, dass wir genau genug über das gewünschte Ergebnis sein müssen.
quelle
Es gibt eine andere Möglichkeit, die ich gefunden habe. Sie müssen eine Klasse erstellen, die von Ihrer Produktklasse abgeleitet ist, und diese verwenden. Zum Beispiel:
Ich bin mir nicht sicher, ob dies "erlaubt" ist, aber es funktioniert.
quelle
Hier ist eine Möglichkeit, dies zu tun, ohne eine zusätzliche Klasse zu deklarieren:
Dies ist jedoch nur zu verwenden, wenn Sie mehrere Entitäten in einer einzigen Entität kombinieren möchten. Die oben genannten Funktionen (einfache Zuordnung von Produkt zu Produkt) werden folgendermaßen ausgeführt:
quelle
Ein anderer einfacher Weg :)
quelle
.ToList
Abfrage eingeben, werden diese ausgeführt und Daten vom Server abgerufen. Was ist dann der Sinn, um sie erneut zu erstellenAsQueryable
?Sie können dies verwenden und es sollte funktionieren -> Sie müssen es verwenden,
toList
bevor Sie die neue Liste mit select erstellen :quelle
Als Antwort auf die andere Frage, die als Duplikat markiert wurde ( siehe hier ), fand ich eine schnelle und einfache Lösung basierend auf der Antwort von Soren:
Hinweis: Diese Lösung funktioniert nur, wenn Sie über eine Navigationseigenschaft (Fremdschlüssel) in der Task-Klasse verfügen (hier als "Vorfall" bezeichnet). Wenn Sie das nicht haben, können Sie einfach eine der anderen veröffentlichten Lösungen mit "AsQueryable ()" verwenden.
quelle
Sie können dies mithilfe von DTOs (Data Transfer Objects) lösen.
Dies sind ein bisschen wie Ansichtsmodelle, in denen Sie die gewünschten Eigenschaften eingeben und diese manuell in Ihrem Controller oder mithilfe von Lösungen von Drittanbietern wie AutoMapper zuordnen können.
Mit DTOs können Sie:
Ich habe dies dieses Jahr in der Schule gelernt und es ist ein sehr nützliches Werkzeug.
quelle
Wenn Sie das Entity-Framework verwenden, entfernen Sie die Eigenschaft aus DbContext, das Ihr komplexes Modell als Entity verwendet. Ich hatte das gleiche Problem, als ich mehrere Modelle einem Ansichtsmodell mit dem Namen Entity zuordnete
Das Entfernen des Eintrags aus DbContext hat meinen Fehler behoben.
quelle
Wenn Sie ausführen
Linq to Entity
, können Sie dasClassType
with nichtnew
zumselect
Schließen der Abfrage verwendenonly anonymous types are allowed (new without type)
Schauen Sie sich diesen Ausschnitt meines Projekts an
von Ihnen haben die
new keyword
in Select-Schließung hinzugefügt, auch wenncomplex properties
Sie diesen Fehler erhaltenweil es in eine SQL-Anweisung umgewandelt und auf SqlServer ausgeführt wird
so , wenn kann ich
new with types
aufselect
Schließung?Sie können es verwenden, wenn Sie es zu tun haben
LINQ to Object (in memory collection)
Nachdem ich
ToList
auf Abfrage ausgeführt wurde, wurde esin memory collection
so, dass wirnew ClassTypes
in select verwenden könnenquelle
In vielen Fällen wird die Transformation nicht benötigt. Überlegen Sie, aus welchem Grund Sie die stark eingegebene Liste verwenden möchten, und bewerten Sie, ob Sie die Daten beispielsweise nur in einem Webdienst oder zum Anzeigen der Daten verwenden möchten. Es spielt keine Rolle, um welchen Typ es sich handelt. Sie müssen nur wissen, wie man es liest und überprüfen, ob es mit den Eigenschaften identisch ist, die in dem von Ihnen definierten anonymen Typ definiert sind. Dies ist das optimale Szenario, da Sie nicht alle Felder einer Entität benötigen und deshalb ein anonymer Typ vorhanden ist.
Ein einfacher Weg ist dies:
quelle
Sie können das Produkt nicht wieder zuordnen, da dies Ihre Tabelle ist, die Sie abfragen. Sie benötigen eine anonyme Funktion, können sie dann einem ViewModel hinzufügen und jedes ViewModel einem hinzufügen
List<MyViewModel>
und diese zurückgeben. Es ist ein kleiner Exkurs, aber ich schließe Vorbehalte zum Umgang mit nullbaren Daten ein, da dies ein Problem für Sie ist, nur für den Fall, dass Sie welche haben. So habe ich damit umgegangen.Hoffentlich haben Sie eine
ProductViewModel
:Ich habe ein Abhängigkeitsinjektions- / Repository-Framework, in dem ich eine Funktion zum Abrufen meiner Daten aufrufe. Am Beispiel Ihres Beitrags in Ihrem Controller-Funktionsaufruf würde dies folgendermaßen aussehen:
In der Repository-Klasse:
Zurück in der Steuerung tun Sie Folgendes:
quelle
füge nur AsEnumerable () hinzu:
quelle
Sie können AsEnumerable wie folgt zu Ihrer Sammlung hinzufügen:
quelle