2016-04-26 25 views
1

Ich habe diesen Code oben und es scheint, dass es nicht richtig zurückgibt. Wenn ich ein anderes Repository in der DB wie Repository2.Query() aufrufen. Wo (?? Code ??). Ich habe den Fehler unten erhalten.Fehler beim Aufruf eines anderen Repos - 'Es ist bereits ein offener DataReader mit diesem Befehl verbunden, der zuerst geschlossen werden muss'

ERROR: { „Es gibt bereits eine offene Datareader mit diesem Befehl zugeordnet, der zuerst geschlossen werden muss“}


Allerdings, wenn ich die Rückkehr zu ICollection ändern <> es Antworten richtig .

public ICollection<Application> GetAppById(Guid Id)      
{ 
     return Repository.Query().Where(c => c.Id == Id).Select(c => c.App).ToList(); 
} 

I IQueryable Rückkehr debuggen, ist kein Fehler, aber ich konnte nicht die Daten finden finden, die es abruft. Der Fehler tritt auf, wenn Sie einen anderen zum Repo aufrufen.

+0

Öffnen Sie einen DataReader an derselben Stelle (oder rufen Sie einen anderen Code auf) an anderer Stelle in Ihrem Programm vor diesem Punkt? Versuchen Sie vielleicht, einen DbContext aus mehreren Threads zu verwenden? – yaakov

+0

Ich Debug IQueryable zurück, es gibt keinen Fehler, aber ich konnte nicht finden, die Daten, die es abruft. Der Fehler tritt auf, wenn Sie einen anderen zum Repo aufrufen. – user1960948

+0

Ich habe das Gefühl, dass der Unterschied nicht in "IQueryable" versus "ICollection" ist, sondern die Tatsache, dass Sie '.ToList()' aufrufen, was Ihre faul abfragbare Stelle sofort auswertet. Ist 'Repository.Query()' Ihr eigener Code oder ist es ein Standardframework (z. B. EntityFramework)? – yaakov

Antwort

2

Die Nachricht ist korrekt; Sie haben zwei Befehle gleichzeitig ausführen lassen. Die erste gezeigte Methode gibt eine "Abfrage" zurück - sie führt alles nicht aus, bis Sie es iterieren - und ist offen, bis Sie stoppen es zu iterieren. Tatsächlich besteht der gesamte Zweck von IQueryable<T> darin, eine zusätzliche Zusammensetzung vor der Ausführung zu ermöglichen. Unter der Annahme, dass Sie foreach verwenden, ist die Abfrage für die Dauer der , nicht der Aufruf an GetAppById selbst aktiv. Also, wenn Sie die klassische "N + 1" tun:

foreach(var row in SomeOuterQuery(...)) { // N+1, not a great idea 
    SomeInnerQuery(row, ...); 
} 

dann sind Sie absolut mehrere gleichzeitige Befehle ausgeführt.

Es gibt drei wichtige Fehlerbehebungen:

  • die erste Abfrage in voller laufen, und dann durchlaufen die Ergebnisse - das ist, was das Hinzufügen ToList tut: den foreach zu innen bewegt GetAppById
  • aktivieren Sie "MARS" (Mehrere aktive Ergebnissätze) - Hinweis: Dies ist kein Ratschlag, einfach ein "das wird funktionieren" (aber: nicht alles, was funktioniert, ist eine gute Idee)
  • restrukturieren Sie die Arbeit, um niemals das "N" in "N + 1" zu benötigen, z. B. durch Abrufen der zusätzlichen Daten gleichzeitig mit der äußeren Liste (mehrere Ergebnisraster aus einer einzelnen Abfrage)
+0

großartig .. das hilft wirklich .. ty – user1960948