Ya hay un DataReader abierto asociado con este comando que debe cerrarse primero

Tengo esta consulta y obtengo el error en esta función:

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

El error es:

Ya hay un DataReader abierto asociado con este comando que debe cerrarse primero.

Actualizar:

seguimiento de stack agregado:

 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 

Esto puede suceder si ejecuta una consulta mientras itera sobre los resultados de otra consulta. No está claro en su ejemplo donde esto sucede porque el ejemplo no está completo.

Una cosa que puede causar esto es la carga diferida desencadenada al iterar sobre los resultados de alguna consulta.

Esto se puede resolver fácilmente al permitir MARS en su cadena de conexión. Agregue MultipleActiveResultSets=true a la parte del proveedor de su cadena de conexión (donde se especifican el origen de datos, el catálogo inicial, etc.).

Puede usar el método ToList() antes de la statement de 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; } 

Aquí hay una cadena de conexión que funciona para alguien que necesita referencia.

     

En mi caso, el uso de Include() resolvió este error y, dependiendo de la situación, puede ser mucho más eficiente que emitir múltiples consultas cuando se puede consultar al mismo tiempo con una combinación.

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

use la syntax .ToList() para convertir el objeto leído de db en una lista para evitar ser releído nuevamente. Espero que esto funcione. Gracias.

No sé si esto es una respuesta duplicada o no. Si lo es, lo siento. Solo quiero que los necesitados sepan cómo resolví mi problema usando ToList ().

En mi caso obtuve la misma excepción para la consulta siguiente.

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

Lo solucioné como a continuación

 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 } 

Parece que está llamando a DateLastUpdated desde una consulta activa que utiliza el mismo contexto EF y DateLastUpdate emite un comando al propio almacén de datos. Entity Framework solo admite un comando activo por contexto a la vez.

Puede refactorizar sus dos consultas anteriores en una como esta:

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

También noté que llamas funciones como FormattedAccountNumber y FormattedRecordNumber en las consultas. A menos que sean objetos o funciones almacenados que haya importado de su base de datos en el modelo de datos de la entidad y correlacionados, también arrojarán excepciones ya que EF no sabrá cómo traducir esas funciones en declaraciones que pueda enviar al almacén de datos.

También tenga en cuenta que llamar a AsEnumerable no obliga a la consulta a ejecutarse. Hasta que la ejecución de la consulta se difiera hasta que se enumere. Puede forzar la enumeración con ToList o ToArray si así lo desea.

Además de la respuesta de Ladislav Mrnka :

Si publica y reemplaza contenedor en la pestaña Configuración , puede establecer MultipleActiveResultSet en True. Puede encontrar esta opción haciendo clic en Avanzado … y estará en el grupo Avanzado .

Tuve el mismo error cuando intenté actualizar algunos registros dentro del ciclo de lectura. He intentado con la respuesta más votada MultipleActiveResultSets=true y encontré que es solo una solución para obtener el siguiente error

Nueva transacción no está permitida porque hay otros subprocesos ejecutándose en la sesión

El mejor enfoque, que funcionará para enormes ResultSets es usar fragmentos y abrir un contexto separado para cada fragmento como se describe en SqlException desde Entity Framework. No se permite nueva transacción porque hay otros subprocesos ejecutándose en la sesión.

Resolví este problema al cambiar await _accountSessionDataModel.SaveChangesAsync (); a _accountSessionDataModel.SaveChanges (); en mi clase de repository.

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

Cambiado a:

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

El problema fue que actualicé las Sesiones en la interfaz después de crear una sesión (en código), pero debido a que SaveChangesAsync ocurre de forma asíncrona, la recuperación de las sesiones causó este error porque aparentemente la operación SaveChangesAsync aún no estaba lista.

Para aquellos que encuentran esto a través de Google;
Estaba obteniendo este error porque, como sugería el error, no cerré un SqlDataReader antes de crear otro en el mismo SqlCommand, asumiendo erróneamente que sería basura recolectada al abandonar el método en el que se creó.

sqlDataReader.Close(); el problema llamando a sqlDataReader.Close(); antes de crear el segundo lector

En mi caso, abrí una consulta desde el contexto de datos, como

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

… y luego consultado lo mismo …

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

Agregar .ToList al primero resolvió mi problema. Creo que tiene sentido envolver esto en una propiedad como:

 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 

Donde _stores es una variable privada, y Filtros también es una propiedad de solo lectura que lee desde AppSettings.

Estoy usando un servicio web en mi herramienta, donde esos servicios obtienen el procedimiento almacenado. mientras más número de herramientas de cliente obtiene el servicio web, surge este problema. Lo he arreglado especificando el atributo Sincronizado para esas funciones que recuperan el procedimiento almacenado. ahora está funcionando bien, el error nunca apareció en mi herramienta.

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

Este atributo permite procesar una solicitud a la vez. así que esto resuelve el problema.

Bueno, para mí fue mi propio error. Estaba intentando ejecutar un INSERT usando SqlCommand.executeReader() cuando debería haber estado usando SqlCommand.ExecuteNonQuery() . Fue abierto y nunca cerrado, causando el error. Tenga cuidado con este descuido.

Esto se extrae de un escenario del mundo real:

  • El código funciona bien en un entorno de escenario con MultipleActiveResultSets se establece en la cadena de conexión
  • Código publicado en Entorno de producción sin MultipleActiveResultSets = true
  • Tantas páginas / llamadas funcionan mientras una sola está fallando
  • Mirando más de cerca la llamada, hay una llamada innecesaria hecha a la base de datos y necesita ser eliminada
  • Establezca MultipleActiveResultSets = true en Producción y publique código limpio, todo funciona bien y, de manera eficiente

En conclusión, sin olvidar MultipleActiveResultSets, el código podría haberse ejecutado durante mucho tiempo antes de descubrir una llamada a base de datos redundantes que podría ser muy costosa, y sugiero no depender completamente de establecer el atributo MultipleActiveResultSets, sino también averiguar por qué el código lo necesita donde falló

Lo más probable es que este problema ocurra debido a la función de “carga diferida” de Entity Framework. Por lo general, a menos que se requiera explícitamente durante la recuperación inicial, todos los datos unidos (cualquier cosa almacenada en otras tablas de bases de datos) se obtienen solo cuando es necesario. En muchos casos, eso es bueno, ya que evita que se obtengan datos innecesarios y, por lo tanto, mejora el rendimiento de la consulta (sin uniones) y ahorra ancho de banda.

En la situación descrita en la pregunta, se realiza una búsqueda inicial, y durante la fase de “selección” se solicitan datos de carga diferida, se emiten consultas adicionales y EF se queja de “abrir DataReader”.

La solución propuesta en la respuesta aceptada permitirá la ejecución de estas consultas, y de hecho la solicitud completa tendrá éxito.

Sin embargo, si va a examinar las solicitudes enviadas a la base de datos, verá varias solicitudes: solicitud adicional por cada dato faltante (cargado de forma diferida). Esto podría ser un asesino de rendimiento.

Un mejor enfoque es decirle a EF que precargue todos los datos necesarios de carga lenta durante la consulta inicial. Esto se puede hacer usando la statement “Incluir”:

 using System.Data.Entity; query = query.Include(a => a.LazyLoadedProperty); 

De esta forma, se realizarán todas las uniones necesarias y se devolverán todos los datos necesarios como una sola consulta. El problema descrito en la pregunta se resolverá.