There is already an open DataReader associated with this Command which must be closed first

匿名 (未验证) 提交于 2019-12-03 02:03:01

问题:

I have this query and I get the error in this function:

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

Error is:

There is already an open DataReader associated with this Command which must be closed first.

Update:

stack trace added:

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.GetEnumerator() +38    System.Linq.Enumerable.Single(IEnumerable`1 source) +114    System.Data.Objects.ELinq.ObjectQueryProvider.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.b__88(AccountsReport account, Int32 index) in D:\Freelance Work\SuperExpert\CreditRegistry\CreditRegistry\Repositories\CreditRegistryRepository.cs:1250    System.Linq.d__7`2.MoveNext() +198    System.Linq.Buffer`1..ctor(IEnumerable`1 source) +217    System.Linq.d__0.MoveNext() +96 

回答1:

This can happen if you execute a query while iterating over the results from another query. It is not clear from your example where this happens because the example is not complete.

One thing that can cause this is lazy loading triggered when iterating over the results of some query.

This can be easily solved by allowing MARS in your connection string. Add MultipleActiveResultSets=true to the provider part of your connection string (where Data Source, Initial Catalog, etc. are specified).



回答2:

You can use the ToList() method before the return statement.

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


回答3:

Here is a working connection string for someone who needs reference.

  


回答4:

In my case, using Include() solved this error and depending on the situation can be a lot more efficient then issuing multiple queries when it can all be queried at once with a join.

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


回答5:

use the syntax .ToList() to convert object read from db to list to avoid being reread again..Hope that would work for it. Thanks.



回答6:

I donot know whether this is duplicate answer or not. If it is I am sorry. I just want to let the needy know how I solved my issue using ToList().

In my case I got same exception for below query.

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

I solved like below

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

It appears that you're calling DateLastUpdated from within an active query using the same EF context and DateLastUpdate issues a command to the data store itself. Entity Framework only supports one active command per context at a time.

You can refactor your above two queries into one like this:

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

I also noticed you're calling functions like FormattedAccountNumber and FormattedRecordNumber in the queries. Unless these are stored procs or functions you've imported from your database into the entity data model and mapped correct, these will also throw excepts as EF will not know how to translate those functions in to statements it can send to the data store.

Also note, calling AsEnumerable doesn't force the query to execute. Until the query execution is deferred until enumerated. You can force enumeration with ToList or ToArray if you so desire.



回答8:

In addition to Ladislav Mrnka's answer:

If you are publishing and overriding container on Settings tab, you can set MultipleActiveResultSet to True. You can find this option by clicking Advanced... and it's going to be under Advanced group.



回答9:

MultipleActiveResultSets=true

New transaction is not allowed because there are other threads running in the session

SqlException from Entity Framework - New transaction is not allowed because there are other threads running in the session



回答10:

I solved this problem by changing await _accountSessionDataModel.SaveChangesAsync(); to _accountSessionDataModel.SaveChanges(); in my Repository class.

 public async Task CreateSession()     {         var session = new Session();          _accountSessionDataModel.Sessions.Add(session);         await _accountSessionDataModel.SaveChangesAsync();      } 

Changed it to:

 public Session CreateSession()     {         var session = new Session();          _accountSessionDataModel.Sessions.Add(session);         _accountSessionDataModel.SaveChanges();      } 

The problem was that I updated the Sessions in the frontend after creating a session (in code), but because SaveChangesAsync happens asynchronously, fetching the sessions caused this error because apparently the SaveChangesAsync operation was not yet ready.



回答11:

In my case, I had opened a query from data context, like

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

... and then subsequently queried the same...

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

Adding the .ToList to the first resolved my issue. I think it makes sense to wrap this in a property like:

Public ReadOnly Property Stores As List(Of Store)     Get         If _stores Is Nothing Then             _stores = DataContext.Stores _                 .Where(Function(d) Filter.Contains(d.code)).ToList         End If         Return _stores     End Get End Property 

Where _stores is a private variable, and Filters is also a readonly property that reads from AppSettings.



回答12:

I am using web service in my tool, where those service fetch the stored procedure. while more number of client tool fetches the web service, this problem arises. I have fixed by specifying the Synchronized attribute for those function fetches the stored procedure. now it is working fine, the error never showed up in my tool.

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

This attribute allows to process one request at a time. so this solves the Issue.



回答13:

For those finding this via Google;
I was getting this error because, as suggested by the error, I failed to close a SqlDataReader prior to creating another on the same SqlCommand, mistakenly assuming that it would be garbage collected when leaving the method it was created in.

I solved the issue by calling sqlDataReader.Close(); before creating the second reader.



回答14:

Well for me it was my own bug. I was trying to run an INSERT using SqlCommand.executeReader() when I should have been using SqlCommand.ExecuteNonQuery(). It was opened and never closed, causing the error. Watch out for this oversight.



回答15:

This is extracted from a real world scenario:

  • Code works well in a Stage environment with MultipleActiveResultSets is set in the connection string
  • Code published to Production environment without MultipleActiveResultSets=true
  • So many pages/calls work while a single one is failing
  • Looking closer at the call, there is an unnecessary call made to the db and needs to be removed
  • Set MultipleActiveResultSets=true in Production and publish cleaned up code, everything works well and, efficiently

In conclusion, without forgetting about MultipleActiveResultSets, the code might have run for a long time before discovering a redundant db call that could be very costly, and I suggest not to fully depend on setting the MultipleActiveResultSets attribute but also find out why the code needs it where it failed.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!