732 votes

Il y a déjà un DataReader ouvert associé à cette commande qui doit d'abord être fermé.

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)
        {
            var dateReported = (from h in context.AccountHistory
                                where h.CreditorRegistryId == creditorRegistryId && h.AccountNo == accountNo
                                select h.LastUpdated).Max();
            return dateReported;
        }

L'erreur est :

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

[EDIT]

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

0 votes

J'ai eu cette erreur lorsque j'avais une requête pour remplir une grille de données ASP.NET MVC Kendo UI où j'ai accidentellement eu des requêtes supplémentaires pour chaque ligne de la requête initiale. Voir ma réponse similaire ici . La solution a été de se débarrasser de cette requête supplémentaire par ligne. Cela a également permis d'améliorer considérablement les performances.

1451voto

Ladislav Mrnka Points 218632

Cela peut se produire si vous exécutez une requête tout en itérant sur les résultats d'une autre requête. Votre exemple ne montre pas clairement où cela se produit, car il n'est pas complet.

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

Ce problème peut être facilement résolu en autorisant MARS dans votre chaîne de connexion. Ajouter MultipleActiveResultSets=true à la partie fournisseur de votre chaîne de connexion (où la source de données, le catalogue initial, etc. sont spécifiés).

41 votes

Cela a fonctionné pour moi. Si vous souhaitez en savoir plus sur l'activation des jeux de résultats actifs multiples (MARS), consultez la page suivante msdn.microsoft.com/fr/us/library/h32h3abf(v=vs.100).aspx . Pensez aussi à vous renseigner sur les inconvénients de MARS. stackoverflow.com/questions/374444/

4 votes

En tenant compte des performances, vous pouvez également résoudre ce problème en incluant System.Data.Entity, puis en utilisant des instructions Include pour vous assurer que ces données secondaires sont chargées dans la requête originale. Si vous activez MARS, le fait de le désactiver pour vérifier ces chargements de données répétés peut contribuer à accélérer vos appels de traitement de données en réduisant les allers-retours.

0 votes

Merci ! Cela a résolu mon problème. Il est intéressant de noter que lors de l'utilisation de LocalDB MultipleActiveResultSets semble être faux par défaut (par opposition à SQL Server ordinaire), ce qui est le problème que je rencontrais.

257voto

Kisame Points 559

Vous pouvez utiliser le ToList() avant la méthode return déclaration.

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

14 votes

J'ai eu cette erreur tellement de fois maintenant... et à chaque fois j'oublie ! La réponse à la question est toujours d'utiliser ToList().

6 votes

Y a-t-il des inconvénients à cela ? Si vous avez 100 000 rangs, je doute que cela puisse être bon.

2 votes

@MartinMazzaDawson , Vous avez vraiment besoin de 100K enregistrements en une seule fois pour l'exécution de la requête ? Je pense que, en utilisant la pagination est une bonne idée pour cette situation.

25voto

Despertar Points 5365

Dans mon cas, en utilisant Include() a résolu cette erreur et, selon la situation, peut être beaucoup plus efficace que de lancer plusieurs requêtes alors que tout peut être interrogé en une seule 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);
            }
        }
    }
}

0 votes

C'est la meilleure solution si votre application ne nécessite pas MARS.

9voto

Ziggler Points 105

Je ne sais pas si c'est une réponse en double ou non. Si c'est le cas, j'en suis désolé. Je veux juste faire savoir à ceux qui en ont besoin comment j'ai résolu mon problème en utilisant ToList().

Dans mon cas, j'ai obtenu 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 le problème comme suit

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
}

0 votes

Je recommande cette approche si vous avez déjà des problèmes avec MARS.

7voto

James Alexander Points 2079

Il semble que vous appelez DateLastUpdated à partir d'une requête active utilisant le même contexte EF et que 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. À moins qu'il ne s'agisse de procédures stockées ou de fonctions que vous avez importées de votre base de données dans le modèle de données de l'entité et que vous avez correctement mappées, ces fonctions vont également générer des excepts car EF ne saura pas comment traduire ces fonctions en instructions qu'il pourra envoyer au magasin de données.

Notez également que l'appel à AsEnumerable ne force pas l'exécution de la requête. L'exécution de la requête est différée jusqu'à l'énumération. Vous pouvez forcer l'énumération avec ToList ou ToArray si vous le souhaitez.

0 votes

Si vous voulez, vous pouvez remanier la requête que vous exécutez pour obtenir la date de dernière mise à jour directement dans votre projection de sélection pour la requête de rapport de comptes et obtenir l'effet désiré sans l'erreur.

0 votes

J'obtiens la même erreur après avoir mis le code de la fonction dans la requête principale.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X