Question Il y a 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 y a déjà un DataReader ouvert associé à cette commande qui doit être fermé en premier.

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

482
2018-05-19 17:01


origine


Réponses:


Cela peut se produire si vous exécutez une requête en parcourant les résultats d'une autre requête. Votre exemple n'indique pas clairement où cela se produit car l'exemple n'est pas complet.

Une chose qui peut provoquer cela est le chargement paresseux déclenché lors de l'itération sur les résultats de certaines requêtes.

Cela peut être facilement résolu en autorisant l'utilisation de 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).


1033
2018-05-19 20:21



Vous pouvez utiliser le ToList() méthode avant la 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;
    }

174
2018-01-14 11:27



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>

14
2017-07-17 04:15



Dans mon cas, en utilisant Include() résolu cette erreur et en fonction de la situation peut être beaucoup plus efficace puis émettre plusieurs requêtes quand il peut tout ê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
2018-04-15 07:05



utiliser la syntaxe .ToList() pour convertir l'objet lu de db en liste pour éviter d'être relu. Espérons que cela fonctionnerait pour cela. Merci.


9
2018-03-15 14:13



Je ne sais pas si c'est une réponse en double ou non. Si c'est le cas, 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
2017-08-25 18:55



Il semble que vous appeliez DateLastUpdated depuis une requête active en 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 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 telles que FormattedAccountNumber et FormattedRecordNumber dans les requêtes. À moins que ces procédures ou fonctions stockées dans votre modèle de données d'entité ne soient importées de votre base de données et mappées correctement, elles renverront également des exemples, car EF ne saura pas comment traduire ces fonctions en instructions pouvant être envoyées au magasin de données.

Notez également qu'appeler 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'à son énumération. Vous pouvez forcer l'énumération avec ToList ou ToArray si vous le désirez.


4
2018-05-19 17:19



En plus de Ladislav Mrnka répondre:

Si vous publiez et remplacez le conteneur sur Paramètres onglet, vous pouvez définir MultipleActiveResultSet à True. Vous pouvez trouver cette option en cliquant sur Avancée... et ça va être sous Avancée groupe.


1
2017-10-17 16:45



J'ai eu la même erreur, lorsque 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 la prochaine erreur

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 ResultSets énormes est d'utiliser des morceaux et d'ouvrir un contexte séparé pour chaque morceau comme décrit dans SqlException from Entity Framework - Nouvelle transaction non autorisée car d'autres threads sont en cours d'exécution dans la session


1
2018-06-01 21:48



J'ai résolu ce problème en changeant wait _accountSessionDataModel.SaveChangesAsync (); à _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();
     }

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 (en code), mais parce que SaveChangesAsync se produit de manière asynchrone, l'extraction des sessions a causé cette erreur car apparemment l'opération SaveChangesAsync n'était pas encore prête.


1
2017-07-21 14:01



Pour ceux qui trouvent cela via Google;
J'obtenais cette erreur car, comme suggéré par l'erreur, je ne parvenais pas à fermer un SqlDataReader avant d'en créer un autre sur la même SqlCommand, en supposant à tort qu'il serait collecté lors de la sortie de la méthode dans laquelle il avait été créé.

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


1
2017-07-21 18:01