Il existe déjà un DataReader ouvert associé à cette commande qui doit être fermé en premier

J'ai cette requête et j'obtiens l'erreur dans cette fonction:

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();
}

L'erreur est:

Il existe déjà un DataReader ouvert associé à cette commande qui doit être fermé en premier.

Mise à Jour:

Trace de pile Ajoutée:

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 WorkSuperExpertCreditRegistryCreditRegistryRepositoriesCreditRegistryRepository.cs:1497
   CreditRegistry.Repositories.CreditRegistryRepository.<AccountDetails>b__88(AccountsReport account, Int32 index) in D:Freelance WorkSuperExpertCreditRegistryCreditRegistryRepositoriesCreditRegistryRepository.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
497
demandé sur abatishchev 2011-05-19 21:01:46

16 réponses

Cela peut se produire si vous exécutez une requête tout en itérant sur les résultats d'une autre requête. Il n'est pas clair d'après votre exemple où cela se produit parce que l'exemple n'est pas complet.

Une chose qui peut causer ceci est le chargement paresseux déclenché lors de l'itération sur les résultats d'une requête.

Cela peut être facilement résolu en autorisant MARS dans votre chaîne de connexion. Ajoutez MultipleActiveResultSets=true à la partie fournisseur de votre chaîne de connexion (où source de données, catalogue Initial, etc. être défini).

1057
répondu Ladislav Mrnka 2013-09-19 00:36:42

Vous pouvez utiliser la méthode ToList() avant l'instruction return.

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;
    }
176
répondu kazem 2014-07-18 13:21:57

Voici une chaîne de connexion de travail pour quelqu'un qui a besoin de référence.

  <connectionStrings>
    <add name="IdentityConnection" connectionString="Data Source=(LocalDb)\v11.0;AttachDbFilename=|DataDirectory|\IdentityDb.mdf;Integrated Security=True;MultipleActiveResultSets=true;" providerName="System.Data.SqlClient" />
  </connectionStrings>
15
répondu Yang Zhang 2015-07-17 04:15:44

Dans mon cas, en utilisant Include() résolu cette erreur et en fonction de la situation peut être beaucoup plus efficace que d'émettre plusieurs requêtes quand il peut tous être interrogé à la fois avec une jointure.

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);
            }
        }
    }
}
13
répondu Despertar 2013-04-15 07:05:08

Utilisez la syntaxe .ToList() pour convertir l'objet lu de la base de données en liste afin d'éviter d'être relu à nouveau.J'espère que cela fonctionnerait pour cela. Grâce.

13
répondu Icemark Muturi 2018-04-18 08:23:04

Je ne sais pas si c'est une réponse en double ou non. Si c'est je suis désolé. Je veux juste que les nécessiteux sachent comment j'ai résolu mon problème en utilisant ToList ().

Dans mon cas, j'ai la même exception pour la requête ci-dessous.

int id = adjustmentContext.InformationRequestOrderLinks.Where(item => item.OrderNumber == irOrderLinkVO.OrderNumber && item.InformationRequestId == irOrderLinkVO.InformationRequestId).Max(item => item.Id);

J'ai résolu comme ci-dessous

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
}
6
répondu Ziggler 2014-08-25 18:55:37

Il semble que vous appelez DateLastUpdated à partir d'une requête active utilisant le même contexte EF et DateLastUpdate envoie une commande au magasin de données lui-même. Entity Framework ne prend en charge qu'une seule commande active par contexte à la fois.

Vous pouvez refactoriser vos deux requêtes ci-dessus en une seule comme ceci:

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

J'ai également remarqué que vous appelez des fonctions comme FormattedAccountNumber et FormattedRecordNumber dans les requêtes. Sauf si ce sont des procs ou des fonctions stockées que vous avez importé de votre base de données dans le modèle de données d'entité et mappé correctement, ceux-ci lanceront également des exceptions car EF ne saura pas comment traduire ces fonctions en instructions qu'il peut envoyer au magasin de données.

Notez également que l'appel à AsEnumerable ne force pas l'exécution de la requête. Jusqu'à ce que l'exécution de la requête soit différée jusqu'à ce qu'elle soit énumérée. Vous pouvez forcer l'énumération avec ToList ou ToArray si vous le désirez.

4
répondu James Alexander 2011-05-19 18:22:51

En plus de la réponsede Ladislav Mrnka:

Si vous publiez et remplacez le conteneur dans l'onglet Settings , Vous pouvez définir MultipleActiveResultSet sur True. Vous pouvez trouver cette option en cliquant sur avancé... et il va être sous - Avancé groupe.

2
répondu Alexander Troshchenko 2014-10-17 16:45:38

J'ai eu la même erreur, quand j'ai essayé de mettre à jour certains enregistrements dans la boucle de lecture. J'ai essayé la réponse la plus votée MultipleActiveResultSets=true et trouvé, que c'est juste une solution de contournement pour obtenir l'erreur suivante

La nouvelle transaction n'est pas autorisée car d'autres threads sont en cours d'exécution dans la session

La meilleure approche, qui fonctionnera pour les ensembles de résultats énormes est d'utiliser des morceaux et d'ouvrir un contexte séparé pour chaque morceau comme décrit dans  SqlException from Entity Framework - la nouvelle transaction est non autorisé car d'autres threads s'exécutent dans la session

1
répondu Michael Freidgeim 2017-05-23 11:55:01

, j'ai résolu ce problème en changeant attendre _accountSessionDataModel.SaveChangesAsync(); de _accountSessionDataModel.SaveChanges(); dans ma classe de Référentiel.

 public async Task<Session> CreateSession()
    {
        var session = new Session();

        _accountSessionDataModel.Sessions.Add(session);
        await _accountSessionDataModel.SaveChangesAsync();
     }

L'a changé en:

 public Session CreateSession()
    {
        var session = new Session();

        _accountSessionDataModel.Sessions.Add(session);
        _accountSessionDataModel.SaveChanges();
     }

Le problème était que j'ai mis à jour les Sessions dans le frontend après avoir créé une session (dans le code), mais comme SaveChangesAsync se produit de manière asynchrone, l'extraction des sessions a provoqué cette erreur car apparemment L'opération SaveChangesAsync n'était pas encore prête.

1
répondu woutercx 2017-07-21 14:01:06

Pour ceux qui trouvent cela via Google;
Je recevais cette erreur parce que, comme suggéré par l'erreur, j'ai échoué à fermer un SqlDataReader avant d'en créer un autre sur le même SqlCommand, en supposant à tort qu'il serait collecté en quittant la méthode dans laquelle il a été créé.

J'ai résolu le problème en appelant sqlDataReader.Close(); avant de créer le deuxième lecteur.

1
répondu timelmer 2017-07-21 18:01:22

Dans mon cas, j'avais ouvert une requête à partir du contexte de données, comme

    Dim stores = DataContext.Stores _
        .Where(Function(d) filter.Contains(d.code)) _

... et puis par la suite interrogé le même...

    Dim stores = DataContext.Stores _
        .Where(Function(d) filter.Contains(d.code)).ToList

L'ajout du .ToList au premier a résolu mon problème. Je pense qu'il est logique d'envelopper cela dans une propriété comme:

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

Où _stores est une variable privée et Filters est également une propriété en lecture seule qui lit à partir D'AppSettings.

1
répondu Adam Cox 2018-03-15 14:41:10

J'utilise le service web dans mon outil, où ces services récupèrent la procédure stockée. alors que plus de nombre d'outils client récupère le service web, ce problème se pose. J'ai corrigé en spécifiant l'attribut synchronisé pour ces fonctions récupère la procédure stockée. maintenant, cela fonctionne bien, l'erreur n'est jamais apparue dans mon outil.

 [MethodImpl(MethodImplOptions.Synchronized)]
 public static List<t> MyDBFunction(string parameter1)
  {
  }

Cet attribut permet de traiter une requête à la fois. si cela résout le Problème.

0
répondu Pranesh Janarthanan 2015-12-28 04:10:36

Eh bien pour moi, c'était mon propre bug. J'essayais d'exécuter un INSERT en utilisant SqlCommand.executeReader() quand j'aurais dû utiliser SqlCommand.ExecuteNonQuery(). Il a été ouvert et jamais fermé, provoquant l'erreur. Watch out pour cette surveillance.

0
répondu Andrew Taylor 2017-07-26 14:56:42

Ceci est extrait d'un scénario réel:

  • le Code fonctionne bien dans un environnement de scène avec MultipleActiveResultSets est défini dans la chaîne de connexion
  • Code publié dans l'environnement de Production sans MultipleActiveResultSets = true
  • Tant de pages / appels fonctionnent alors qu'un seul échoue
  • en regardant de plus près l'appel, il y a un appel inutile fait à la base de données et doit être supprimé
  • Définir MultipleActiveResultSets=true dans la Production et la publication de code nettoyé, tout fonctionne bien et, efficacement

En conclusion, sans oublier MultipleActiveResultSets, le code pourrait avoir fonctionné pendant longtemps avant de découvrir un appel DB redondant qui pourrait être très coûteux, et je suggère de ne pas dépendre entièrement de la définition de L'attribut MultipleActiveResultSets mais aussi découvrez pourquoi le code en a besoin là où il a échoué.

0
répondu usefulBee 2017-09-06 17:54:02

Très probablement ce problème se produit en raison de la fonctionnalité" chargement paresseux " de Entity Framework. Habituellement, à moins d'être explicitement requis lors de l'extraction initiale, toutes les données jointes (tout ce qui est stocké dans d'autres tables de base de données) ne sont récupérées que lorsque cela est nécessaire. Dans de nombreux cas, c'est une bonne chose, car cela empêche d'extraire des données inutiles et améliore ainsi les performances de la requête (Pas de jointures) et économise de la bande passante.

Dans la situation décrite dans la question, l'extraction initiale est effectuée, et pendant phase" select "les données de chargement paresseux manquantes sont demandées, des requêtes supplémentaires sont émises et EF se plaint de "open DataReader".

La solution de contournement proposée dans la réponse acceptée permettra l'exécution de ces requêtes, et en effet toute la requête réussira.

Cependant, si vous examinez les requêtes envoyées à la base de données, vous remarquerez plusieurs requêtes - Requête supplémentaire pour chaque donnée manquante (chargée paresseuse). Cela pourrait être un tueur de performance.

Un meilleur l'approche consiste à dire à EF de précharger toutes les données chargées paresseuses nécessaires pendant la requête initiale. Cela peut être fait en utilisant l'instruction "Include":

using System.Data.Entity;

query = query.Include(a => a.LazyLoadedProperty);

De cette façon, toutes les jointures nécessaires seront effectuées et toutes les données nécessaires seront retournées en tant que requête unique. Le problème décrit dans la question sera résolue.

0
répondu Illidan 2018-03-31 10:45:43