Ich habe diese Abfrage und ich bekomme den Fehler in dieser Funktion:
var accounts = from account in context.Accounts
from guranteer in account.Gurantors
select new AccountsReport
{
CreditRegistryId = account.CreditRegistryId,
AccountNumber = account.AccountNo,
DateOpened = account.DateOpened,
};
return accounts.AsEnumerable()
.Select((account, index) => new AccountsReport()
{
RecordNumber = FormattedRowNumber(account, index + 1),
CreditRegistryId = account.CreditRegistryId,
DateLastUpdated = DateLastUpdated(account.CreditRegistryId, account.AccountNumber),
AccountNumber = FormattedAccountNumber(account.AccountType, account.AccountNumber)
})
.OrderBy(c=>c.FormattedRecordNumber)
.ThenByDescending(c => c.StateChangeDate);
public DateTime DateLastUpdated(long creditorRegistryId, string accountNo)
{
return (from h in context.AccountHistory
where h.CreditorRegistryId == creditorRegistryId && h.AccountNo == accountNo
select h.LastUpdated).Max();
}
Fehler ist:
Mit diesem Befehl ist bereits ein offener DataReader verbunden, der zuerst geschlossen werden muss.
Update:
stack-Trace hinzugefügt:
InvalidOperationException: There is already an open DataReader associated with this Command which must be closed first.]
System.Data.SqlClient.SqlInternalConnectionTds.ValidateConnectionForExecute(SqlCommand command) +5008639
System.Data.SqlClient.SqlConnection.ValidateConnectionForExecute(String method, SqlCommand command) +23
System.Data.SqlClient.SqlCommand.ValidateCommand(String method, Boolean async) +144
System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result) +87
System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method) +32
System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method) +141
System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior) +12
System.Data.Common.DbCommand.ExecuteReader(CommandBehavior behavior) +10
System.Data.EntityClient.EntityCommandDefinition.ExecuteStoreCommands(EntityCommand entityCommand, CommandBehavior behavior) +443
[EntityCommandExecutionException: An error occurred while executing the command definition. See the inner exception for details.]
System.Data.EntityClient.EntityCommandDefinition.ExecuteStoreCommands(EntityCommand entityCommand, CommandBehavior behavior) +479
System.Data.Objects.Internal.ObjectQueryExecutionPlan.Execute(ObjectContext context, ObjectParameterCollection parameterValues) +683
System.Data.Objects.ObjectQuery`1.GetResults(Nullable`1 forMergeOption) +119
System.Data.Objects.ObjectQuery`1.System.Collections.Generic.IEnumerable<T>.GetEnumerator() +38
System.Linq.Enumerable.Single(IEnumerable`1 source) +114
System.Data.Objects.ELinq.ObjectQueryProvider.<GetElementFunction>b__3(IEnumerable`1 sequence) +4
System.Data.Objects.ELinq.ObjectQueryProvider.ExecuteSingle(IEnumerable`1 query, Expression queryRoot) +29
System.Data.Objects.ELinq.ObjectQueryProvider.System.Linq.IQueryProvider.Execute(Expression expression) +91
System.Data.Entity.Internal.Linq.DbQueryProvider.Execute(Expression expression) +69
System.Linq.Queryable.Max(IQueryable`1 source) +216
CreditRegistry.Repositories.CreditRegistryRepository.DateLastUpdated(Int64 creditorRegistryId, String accountNo) in D:\Freelance Work\SuperExpert\CreditRegistry\CreditRegistry\Repositories\CreditRegistryRepository.cs:1497
CreditRegistry.Repositories.CreditRegistryRepository.<AccountDetails>b__88(AccountsReport account, Int32 index) in D:\Freelance Work\SuperExpert\CreditRegistry\CreditRegistry\Repositories\CreditRegistryRepository.cs:1250
System.Linq.<SelectIterator>d__7`2.MoveNext() +198
System.Linq.Buffer`1..ctor(IEnumerable`1 source) +217
System.Linq.<GetEnumerator>d__0.MoveNext() +96
Dies kann vorkommen, wenn Sie eine Abfrage ausführen, während Sie die Ergebnisse einer anderen Abfrage durchlaufen. Aus Ihrem Beispiel ist nicht klar, wo dies geschieht, weil das Beispiel nicht vollständig ist.
Eine Sache, die dazu führen kann, ist das langsame Laden, das ausgelöst wird, wenn die Ergebnisse einer Abfrage durchlaufen werden.
Dies kann leicht gelöst werden, indem Sie MARS in Ihrer Verbindungszeichenfolge zulassen. Fügen Sie dem Providerteil Ihrer Verbindungszeichenfolge MultipleActiveResultSets=true
hinzu (wobei Datenquelle, Anfangskatalog usw. angegeben sind).
Sie können die ToList()
-Methode vor der return
-Anweisung verwenden.
var accounts =
from account in context.Accounts
from guranteer in account.Gurantors
select new AccountsReport
{
CreditRegistryId = account.CreditRegistryId,
AccountNumber = account.AccountNo,
DateOpened = account.DateOpened,
};
return accounts.AsEnumerable()
.Select((account, index) => new AccountsReport()
{
RecordNumber = FormattedRowNumber(account, index + 1),
CreditRegistryId = account.CreditRegistryId,
DateLastUpdated = DateLastUpdated(account.CreditRegistryId, account.AccountNumber),
AccountNumber = FormattedAccountNumber(account.AccountType, account.AccountNumber)}).OrderBy(c=>c.FormattedRecordNumber).ThenByDescending(c => c.StateChangeDate).ToList();
public DateTime DateLastUpdated(long creditorRegistryId, string accountNo)
{
var dateReported = (from h in context.AccountHistory
where h.CreditorRegistryId == creditorRegistryId && h.AccountNo == accountNo
select h.LastUpdated).Max();
return dateReported;
}
verwenden Sie die Syntax .ToList()
, um das aus db gelesene Objekt in eine Liste umzuwandeln, um ein erneutes Lesen zu vermeiden. Vielen Dank.
Hier ist eine funktionierende Verbindungszeichenfolge für jemanden, der einen Verweis benötigt.
<connectionStrings>
<add name="IdentityConnection" connectionString="Data Source=(LocalDb)\v11.0;AttachDbFilename=|DataDirectory|\IdentityDb.mdf;Integrated Security=True;MultipleActiveResultSets=true;" providerName="System.Data.SqlClient" />
</connectionStrings>
In meinem Fall konnte der Fehler mithilfe von Include()
behoben werden. Je nach Situation kann es wesentlich effizienter sein, mehrere Abfragen auszugeben, wenn alle gleichzeitig mit einem Join abgerufen werden können.
IEnumerable<User> users = db.Users.Include("Projects.Tasks.Messages");
foreach (User user in users)
{
Console.WriteLine(user.Name);
foreach (Project project in user.Projects)
{
Console.WriteLine("\t"+project.Name);
foreach (Task task in project.Tasks)
{
Console.WriteLine("\t\t" + task.Subject);
foreach (Message message in task.Messages)
{
Console.WriteLine("\t\t\t" + message.Text);
}
}
}
}
Ich weiß nicht, ob dies eine doppelte Antwort ist oder nicht. Wenn es mir leid tut. Ich möchte nur den Bedürftigen mitteilen, wie ich mein Problem mit ToList () gelöst habe.
In meinem Fall bekam ich die gleiche Ausnahme für die unten stehende Abfrage.
int id = adjustmentContext.InformationRequestOrderLinks.Where(item => item.OrderNumber == irOrderLinkVO.OrderNumber && item.InformationRequestId == irOrderLinkVO.InformationRequestId).Max(item => item.Id);
Ich löste mich wie folgt
List<Entities.InformationRequestOrderLink> links = adjustmentContext.InformationRequestOrderLinks
.Where(item => item.OrderNumber == irOrderLinkVO.OrderNumber && item.InformationRequestId == irOrderLinkVO.InformationRequestId).ToList();
int id = 0;
if (links.Any())
{
id = links.Max(x => x.Id);
}
if (id == 0)
{
//do something here
}
Es scheint, dass Sie DateLastUpdated innerhalb einer aktiven Abfrage mit demselben EF-Kontext aufrufen, und DateLastUpdate gibt einen Befehl an den Datenspeicher selbst aus. Entity Framework unterstützt jeweils nur einen aktiven Befehl pro Kontext.
Sie können Ihre zwei oben genannten Abfragen folgendermaßen umwandeln:
return accounts.AsEnumerable()
.Select((account, index) => new AccountsReport()
{
RecordNumber = FormattedRowNumber(account, index + 1),
CreditRegistryId = account.CreditRegistryId,
DateLastUpdated = (
from h in context.AccountHistory
where h.CreditorRegistryId == creditorRegistryId
&& h.AccountNo == accountNo
select h.LastUpdated).Max(),
AccountNumber = FormattedAccountNumber(account.AccountType, account.AccountNumber)
})
.OrderBy(c=>c.FormattedRecordNumber)
.ThenByDescending(c => c.StateChangeDate);
Ich habe auch bemerkt, dass Sie in den Abfragen Funktionen wie FormattedAccountNumber und FormattedRecordNumber aufrufen. Wenn diese nicht als gespeicherte Prozeduren oder Funktionen gespeichert sind, die Sie aus Ihrer Datenbank in das Entitätsdatenmodell importiert und korrekt zugeordnet haben, werden auch diese Ausnahmen ausgelöst, da EF die Funktionen nicht in Anweisungen übersetzen kann, die er an den Datenspeicher senden kann.
Beachten Sie auch, dass das Aufrufen von AsEnumerable die Ausführung der Abfrage nicht erzwingt. Bis die Abfrageausführung verzögert wird, bis sie aufgelistet wird. Sie können die Aufzählung mit ToList oder ToArray erzwingen, wenn Sie dies wünschen.
Zusätzlich zu Ladislav Mrnkas Antwort:
Wenn Sie Container auf der Registerkarte Settings veröffentlichen und überschreiben, können Sie MultipleActiveResultSet auf True setzen. Sie können diese Option finden, indem Sie auf Erweitert ... klicken und sich in der Gruppe Erweitert befinden.
In meinem Fall hatte ich eine Abfrage aus dem Datenkontext geöffnet, z
Dim stores = DataContext.Stores _
.Where(Function(d) filter.Contains(d.code)) _
... und dann gleich danach abgefragt ...
Dim stores = DataContext.Stores _
.Where(Function(d) filter.Contains(d.code)).ToList
Das Hinzufügen des .ToList
zum ersten hat mein Problem behoben. Ich denke, es macht Sinn, dies in eine Eigenschaft wie zu verpacken:
Public ReadOnly Property Stores As List(Of Store)
Get
If _stores Is Nothing Then
_stores = DataContext.Stores _
.Where(Function(d) Filters.Contains(d.code)).ToList
End If
Return _stores
End Get
End Property
Dabei ist _stores eine private Variable und Filters ist auch eine Readonly-Eigenschaft, die aus AppSettings liest.
Ich hatte den gleichen Fehler, als ich versuchte, einige Datensätze innerhalb der Leseschleife zu aktualisieren. Ich habe die am meisten gewählte Antwort MultipleActiveResultSets=true
ausprobiert und festgestellt, dass es nur eine Problemumgehung ist, um den nächsten Fehler zu erhalten
Neue Transaktion ist nicht zulässig, da andere Threads ausgeführt werden in der Sitzung
Der beste Ansatz für große ResultSets ist die Verwendung von Chunks und das Öffnen eines separaten Kontexts für jeden Chunk, wie in SqlException von Entity Framework beschrieben. Neue Transaktion ist nicht zulässig, da andere Threads in der Sitzung ausgeführt werden.
Für diejenigen, die dies über Google finden;
Dieser Fehler wurde angezeigt, da ich, wie durch den Fehler vorgeschlagen, einen SqlDataReader nicht schließen konnte, bevor er einen anderen SqlCommand erstellt, und davon ausging, dass er beim Ablegen der Methode, die er erstellt hat, Müll ist.
Ich habe das Problem gelöst, indem ich sqlDataReader.Close();
aufgerufen habe, bevor ich den zweiten Reader erstellt habe.
Ich habe dieses Problem durch Ändern von Await _accountSessionDataModel.SaveChangesAsync (); In _ accountSessionDataModel.SaveChanges (); In meiner Repository-Klasse gelöst.
public async Task<Session> CreateSession()
{
var session = new Session();
_accountSessionDataModel.Sessions.Add(session);
await _accountSessionDataModel.SaveChangesAsync();
}
Geändert zu:
public Session CreateSession()
{
var session = new Session();
_accountSessionDataModel.Sessions.Add(session);
_accountSessionDataModel.SaveChanges();
}
Das Problem war, dass ich die Sitzungen im Frontend nach dem Erstellen einer Sitzung (im Code) aktualisiert habe. Da SaveChangesAsync jedoch asynchron ausgeführt wird, hat das Abrufen der Sitzungen diesen Fehler verursacht, da der Vorgang SaveChangesAsync anscheinend noch nicht bereit war.
Dieses Problem tritt höchstwahrscheinlich aufgrund des "Lazy Loading" -Features von Entity Framework auf. Normalerweise werden alle verbundenen Daten (alle Daten, die in anderen Datenbanktabellen gespeichert sind) nur dann abgerufen, wenn dies beim anfänglichen Abruf explizit erforderlich ist. In vielen Fällen ist dies eine gute Sache, da es das Abrufen unnötiger Daten verhindert und somit die Abfrageleistung verbessert (keine Verknüpfungen) und Bandbreite eingespart wird.
In der in der Frage beschriebenen Situation wird ein erster Abruf durchgeführt, und während der "Auswahl" -Phase werden fehlende Lazy-Loading-Daten angefordert, zusätzliche Abfragen ausgegeben und EF beschwert sich über "Open DataReader".
Die in der akzeptierten Antwort vorgeschlagene Problemumgehung ermöglicht die Ausführung dieser Abfragen, und tatsächlich wird die gesamte Anforderung erfolgreich sein.
Wenn Sie jedoch Anforderungen prüfen, die an die Datenbank gesendet werden, werden Sie mehrere Anforderungen feststellen - zusätzliche Anforderungen für alle fehlenden (faul geladenen) Daten. Dies könnte ein Performancekiller sein.
Besser ist es, EF zu sagen, dass er während der ersten Abfrage alle benötigten Lazy-Load-Daten vorab laden muss. Dies kann mit der Include-Anweisung erfolgen:
using System.Data.Entity;
query = query.Include(a => a.LazyLoadedProperty);
Auf diese Weise werden alle erforderlichen Joins ausgeführt und alle benötigten Daten werden als einzelne Abfrage zurückgegeben. Das in der Frage beschriebene Problem wird gelöst.
Ich verwende einen Webdienst in meinem Tool, bei dem die gespeicherte Prozedur abgerufen wird. Während eine größere Anzahl von Client-Tools den Web-Service abruft, tritt dieses Problem auf. Ich habe das Problem behoben, indem ich das Synchronized-Attribut für diese Funktion angegeben habe, um die gespeicherte Prozedur abzurufen. jetzt funktioniert es gut, der Fehler ist in meinem Werkzeug nie aufgetaucht.
[MethodImpl(MethodImplOptions.Synchronized)]
public static List<t> MyDBFunction(string parameter1)
{
}
Dieses Attribut erlaubt es, jeweils eine Anfrage zu bearbeiten. das löst also das Problem.
In meinem Fall musste ich die MultipleActiveResultSets
in der Verbindungszeichenfolge auf True
setzen.
Dann trat ein weiterer Fehler auf (der echte), weil 2 (SQL) -Befehle nicht gleichzeitig über denselben Datenkontext ausgeführt werden konnten! (EF Core, Code zuerst)
Also bestand die Lösung für mich darin, nach einer anderen asynchronen Befehlsausführung zu suchen und sie in synchron umzuwandeln, da ich nur einen DbContext für beide Befehle hatte.
Ich hoffe es hilft dir
Für mich war es mein eigener Fehler. Ich habe versucht, eine INSERT
mit SqlCommand.executeReader()
auszuführen, wenn ich SqlCommand.ExecuteNonQuery()
hätte verwenden sollen. Es wurde geöffnet und nie geschlossen, wodurch der Fehler verursacht wurde. Achten Sie auf dieses Versehen.
Als Randbemerkung ... kann dies auch passieren, wenn ein Problem mit der (internen) Datenzuordnung von SQL-Objekten auftritt.
Zum Beispiel...
Ich habe einen SQL Scalar Function
erstellt, der versehentlich eine VARCHAR
... zurückgegeben hat, und dann ... eine Spalte in einer VIEW
erstellt. Die VIEW
wurde korrekt in der DbContext
... abgebildet. So Linq nannte es einfach gut. Die Entity erwartete DateTime? und die VIEW
gab String zurück.
Was wirft ODDLY ...
"Es ist bereits ein offener DataReader mit diesem Befehl verbunden Der muss zuerst geschlossen werden."
Es war schwer herauszufinden, aber nachdem ich die Rückgabeparameter korrigiert hatte, war alles gut
Dies wird aus einem realen Szenario extrahiert:
Zusammenfassend kann gesagt werden, dass der Code, ohne MultipleActiveResultSets zu vergessen, lange Zeit ausgeführt wurde, bevor ein redundanter db-Aufruf entdeckt wurde, der sehr kostspielig sein kann, und ich schlage vor, nicht vollständig auf das Attribut MultipleActiveResultSets, sondern auch auf find out) zu setzen warum der Code es benötigt, wo es fehlgeschlagen ist.