Wie soll ich die Entity Framework-Tabellenreferenz (Fremd-) Liste von jedem Objekt deaktivieren?

8

Ich verwende SQLite-Datenbank und System.Data.SQLite 1.0.92 Es gibt 2 Tische hier:

Tischperson :

PersonID

PersonenName

Tischschüler :

Schüler-ID

PersonId (Referenztabelle Person FK)

StudentNein

Jetzt jedes Mal, wenn ich die Personen Sammlung in EF5 bekomme:

%Vor%

Es gibt auch AllPersons.student Sammlung wird in das Ergebnis enthalten;

Aber ich brauche es nicht. Natürlich ist das nur ein Beispiel, es gibt eine Menge große Tabellen, die so viele Referenzen haben, es hat deswegen immer Performance-Probleme.

Also versuche ich es nicht in meinem Ergebnis zu lassen. Also ändere ich es:

%Vor%

Nun gut, denn AllPersons.student collection ist immer null

Aber jetzt habe ich gefunden: Wenn ich Person und Schüler zusammen zusammen :

%Vor%

Jetzt ist die Referenz noch enthalten.

Also Gibt es in zu jeder Zeit in dieser Situation ? Danke.

Aktualisieren

Für einige Freunde Anfrage, erkläre ich, warum ich es brauche:

1: Wenn ich es in json umwandle, wird es eine tote Schleife sein. sogar ich benutze bereits Json.net ReferenceLoopHandling , die json größe ist sehr groß um den server zu crashen (wenn keine referenzen, es ist nur ein sehr kleiner json)

2: Jedes Mal, wenn ich die Kundendaten erhalte und speichern muss, wird eine Ausnahme zum Modellstatus angezeigt, bis ich sie auf null setze.

Beispiel:

%Vor%

3: Das ist ein wichtigeres Problem. Ich bekomme bereits alle Daten und Cache auf dem Server. Aber es wird die Ladezeit beim Serverstart sehr lang sein. (weil die Daten und Referenzen so viele sind, das ist das Hauptproblem), ich weiß nicht, ob ich wieder welche Art von Problem finden werde ....

%Vor%     
qakmak 29.06.2015, 04:37
quelle

9 Antworten

3

Das Problem

Wie Sie gesagt haben, wenn Sie sowohl die Eltern- als auch die Kinderliste laden, auch wenn LazyLoading deaktiviert ist, und dann in übergeordnete Elemente suchen. Untergeordnete Elemente werden ebenfalls angezeigt.

%Vor%

Was ist passiert? Warum sind Kinder in einem Elternteil enthalten?

Die untergeordneten Elemente einer untergeordneten Entität sind diejenigen, die Sie mithilfe von db.YourChildSet.ToList(); Genau selbst geladen haben. Tatsächlich lädt Entity Framework nie wieder Childs für ein Elternelement, aber wegen der Beziehung zwischen Eltern und Kind in edmx werden sie dort aufgelistet.

Beeinflusst das Perforemance?

Entsprechend der Tatsache, dass Childs nur einmal laden, hat es keinen Einfluss auf die Fortschreibung, weil Daten geladen werden.

Aber für die Serialisierung oder etwas anderes, Wie kann ich es loswerden?

Sie können diese Lösungen verwenden:

Lösung 1:

Verwenden Sie 2 verschiedene Instanzen von YourDbContext:

%Vor%
  • Wenn Sie nun in eltern suchen.Kinder gibt es kein Kind darin.

Lösung 2:

Nutzen Sie Projektion und gestalten Sie Ihre Ausgabe nach Ihrem Willen und verwenden Sie sie.

%Vor%
  • So ist bei der Serialisierung nichts störend.
  • Die Verwendung einer benutzerdefinierten Model-Klasse ist optional und wird in einigen Fällen empfohlen.

Weitere Ressourcen

Als Entwickler, der Entity Framework verwendet, wird das Lesen dieser Ressourcen dringend empfohlen:

Reza Aghaei 28.08.2015, 17:27
quelle
2

Ich konzentriere mich auf Ihr drittes Problem , denn das scheint Ihr dringendstes Problem zu sein. Dann werde ich versuchen, einige Hinweise zu den anderen beiden Problemen zu geben.

Es gibt zwei Entity Framework-Features, die Sie beachten sollten:

  1. Wenn Sie Daten in einen Kontext laden, versucht Entity Framework, die Objekte dort zu verbinden, wo sie zugeordnet sind. Dies wird als relationship fixup bezeichnet. Sie können EF nicht davon abhalten. Wenn Sie also Persons und Students separat laden, enthält eine Person s Students sammlung Schüler, obwohl Sie Include() sie nicht haben.

  2. Standardmäßig speichert ein Kontext alle Daten, die er von der Datenbank abruft. Darüber hinaus speichert es Metadaten über die Objekte in seinem Änderungsverfolger: Kopien ihrer individuellen Eigenschaften und alle Zuordnungen. Durch das Laden vieler Objekte wächst also der interne Cache, aber auch die Größe der Metadaten. Und der Prozess der fortlaufenden Beziehungsfixierung wird immer langsamer (obwohl dies helfen kann, ihn zu verschieben, indem die automatische Änderungserkennung deaktiviert wird). Alles in allem wird der Kontext aufgebläht und langsam wie ein schlaffes Nashorn.

Ich verstehe, dass Sie Daten in separaten Sammlungen für jede Entität zwischenspeichern möchten. Zwei einfache Änderungen machen das viel schneller:

  • Vermeiden Sie die unvermeidliche Korrektur der Beziehung, indem Sie jede Sammlung in einen separaten Kontext laden
  • Stoppen Sie das Zwischenspeichern (im Kontext) und ändern Sie die Verfolgung, indem Sie die Daten mit AsNoTracking .
  • abrufen

Dadurch sieht Ihr Code wie folgt aus:

%Vor%

Der Grund für das Deaktivieren von ProxyCreationEnabled ist, dass Sie leichte Objekte erhalten und niemals versehentlich Lazy Loading auslösen werden (Ausnahme wird ausgelöst, wenn der Kontext nicht mehr verfügbar ist).

Jetzt haben Sie Objekte zwischengespeichert, die nicht miteinander verwandt sind und die so schnell abgerufen werden, wie es mit EF möglich ist. Wenn das nicht schnell genug ist, müssen Sie auf andere Tools wie Dapper zurückgreifen.

Übrigens, Ihr allererstes Code-Snippet und Ihre Problembeschreibung ...

%Vor%      

Es gibt auch eine AllPersons.student-Auflistung, die in das Ergebnis aufgenommen wird;

... schlagen vor, dass das Entity Framework spontan das eifrige Laden (von Studenten) durchführt, ohne dass Sie Include -ing. Ich muss davon ausgehen, dass Ihr Code-Snippet nicht vollständig ist. EF führt niemals automatisch eifriges Laden aus. (Es sei denn, Sie haben vielleicht einen ausgefallenen und fehlerhaften Abfrageanbieter).

Wie für das erste Problem , die Serialisierung. Sie sollten das in ähnlicher Weise wie oben gezeigt angehen können. Laden Sie einfach die Daten, die Sie serialisieren möchten, isoliert und deaktivieren Sie die Proxy-Erstellung. Oder, wie von anderen vorgeschlagen, serialisieren Sie Ansichtsmodelle oder anonyme Typen, die genau das enthalten, was Sie dort benötigen.

Wie für das zweite Problem , die Validierungsausnahme. Ich kann mir nur vorstellen, dass dies passiert, wenn Sie eine Schülerkollektion standardmäßig mit leeren, Student -Objekten initialisieren. Diese sind zwangsläufig ungültig. Wenn dies nicht der Fall ist, schlage ich vor, dass Sie eine neue Frage zu diesem speziellen Problem stellen, die ausführlich über die beteiligten Klassen und Abbildungen informiert. Das sollte in dieser Frage nicht behandelt werden.

    
Gert Arnold 28.08.2015 21:25
quelle
0

Wenn Entitäten automatisch generiert werden, kopieren Sie sie in den eigenen Code und entfernen Sie die erzeugte Beziehung wie untergeordnete Sammlung und Fremdschlüssel. Oder Sie brauchen nicht alle diese Art von Funktionalität könnte Benutzer leichtgewichtiges Framework wie dapper

    
Rohit Harkhani 17.07.2015 09:01
quelle
0

Normalerweise füllt Ihre Kursteilnehmersammlung nicht aus der Datenbank. Es ist satt, wenn Sie zu Eigentum gelangen. Wenn Sie die ToList () - Methode verwenden, liest Entity Framework außerdem Daten aus Daten, um Ihre Sammlung zu füllen.

Bitte überprüfen Sie dies. Ссылка Ссылка

    
Yargicx 19.07.2015 23:55
quelle
0
  

Gibt es in diesem Fall trotzdem die Möglichkeit, den Verweis in einzufügen ?

Die Lösung scheint sehr einfach zu sein: Ordnen Sie die Assoziation nicht zu. Entfernen Sie die Student -Auflistung. Nicht viel mehr kann ich dazu sagen.

    
Gert Arnold 23.08.2015 20:35
quelle
0

Verzieren Sie alle Eigenschaften mit [IgnoreDataMember] , wenn Sie 4.5 +

verwenden

Ссылка

Klingt auch so, als ob Sie versuchen, Tabellenvererbung durchzuführen, was ein anderes Problem mit EF ist.

Ссылка

Ссылка

    
TombMedia 23.08.2015 21:52
quelle
0

Wählen Sie explizit aus, was Sie von der Datenbank zurückgeben möchten.

Verwenden Sie Select new . Mit der Klausel select new können Sie neue Objekte eines anonymen Typs als Ergebnis einer Abfrage erstellen und den Verweis nicht einbeziehen. Mit dieser Syntax können Sie anonyme Datenstrukturen erstellen. Diese werden erstellt, wenn sie (träge) ausgewertet werden. So:

%Vor%

Und selbst müssen Sie das Lazy Loading nicht mehr deaktivieren .

Nach dem Ausführen der Abfrage oben:

Diese Abfrage weist derzeit einen anonymen Typ unter Verwendung von select new { } zu, für den Sie var verwenden müssen. Wenn Sie einen bekannten Typ zuordnen möchten, fügen Sie ihn zu Ihrer SELECT-Klausel hinzu:

%Vor%

Und:

%Vor%     
S.Akbari 23.08.2015 17:48
quelle
0

Wenn ich Sie richtig verstehe, versuchen Sie nur sicherzustellen, dass Sie nur das bekommen, wonach Sie ausdrücklich fragen, richtig?

Dies wurde etwas oben erwähnt, aber um dies richtig zu machen, möchten Sie nur einen anonymen Typ auswählen.

%Vor%

Wenn Sie diese Sammlung / dieses Objekt aktualisieren möchten, würde ich GraphDiff empfehlen. GraphDiff hilft wirklich bei Problemen mit getrennten Entitäten und Aktualisierungen ( Ссылка )

So würde Ihre Methode ähnlich aussehen:

%Vor%

Auf diese Weise können Sie alle Eigenschaften eines Objekts aktualisieren, unabhängig davon, ob die Verbindung getrennt ist oder nicht, und Sie müssen sich nicht um die Zuordnung kümmern.

Dies setzt voraus, dass Sie Ihre Entitäten korrekt zugeordnet haben, und ehrlich gesagt, finde ich es einfacher, das Objekt als eine Eigenschaft zu deklarieren, nicht nur die ID, und verwenden Sie eine Zuordnungsdatei, um es korrekt zuzuordnen.

Also:

%Vor%

Hoffentlich macht das Sinn. Sie müssen kein Ansichtsmodell erstellen, aber Sie können es auf jeden Fall. Auf diese Weise wird es einfacher, getrennte Elemente zurück in die Datenbank zu mappen.

    
Andy Poquette 24.08.2015 20:46
quelle
-1

Sie sind automatisch in ObjectContext von dort EntityKey verknüpft. Abhängig davon, was Sie mit Ihrem Persons und Students machen möchten, können Sie Detach sie aus dem ObjectContext :

%Vor%     
stephanejulien 14.07.2015 11:53
quelle