it-swarm.com.de

Mit diesem Befehl ist bereits ein offener DataReader verbunden, der zuerst geschlossen werden muss

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
522
DotnetSparrow

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).

1102
Ladislav Mrnka

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;
    }
186
kazem

verwenden Sie die Syntax .ToList(), um das aus db gelesene Objekt in eine Liste umzuwandeln, um ein erneutes Lesen zu vermeiden. Vielen Dank.

18
Icemark Muturi

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>
16
Yang Zhang

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);
            }
        }
    }
}
15
Despertar

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
}
7
Ziggler

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.

4
James Alexander

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.

2
Adam Cox

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.

1

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.

1
timelmer

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.

1
woutercx

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.

1
Illidan

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. 

0

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

0
Dr TJ

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.

0
Andrew Taylor

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

0
Prisoner ZERO

Dies wird aus einem realen Szenario extrahiert:

  • Code funktioniert gut in einer Stage-Umgebung, in der MultipleActiveResultSets in der Verbindungszeichenfolge festgelegt ist
  • In der Produktionsumgebung veröffentlichter Code ohne MultipleActiveResultSets = true
  • So viele Seiten/Aufrufe funktionieren, während eine einzelne fehlschlägt
  • Bei näherer Betrachtung des Anrufs wird ein unnötiger Anruf an die Datenbankbibliothek gerichtet und muss entfernt werden
  • Setzen Sie MultipleActiveResultSets = true in Production und veröffentlichen Sie bereinigten Code. Alles funktioniert gut und effizient

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

0
usefulBee