Ya hay un DataReader abierto asociado a esta connection que debe cerrarse primero + asp.net mvc

Tengo una database mysql con una tabla enttes con múltiples campos en ella como entity_title, entity_description, …. En la tabla también hay 3 keys externas user_id , region_id y category_id .

En mi vista de índice, me gustaría mostrar todas las entidades en una tabla (mostrar el título, la descripción, …, el nombre de usuario, el nombre de la región y el nombre de la categoría).

Esto es lo que hago en mi controller:

public ActionResult Index() { var model = this.UnitOfWork.EntityRepository.Get(); return View(model); } 

En mi repository, hago esto:

 public virtual IEnumerable<TEntity> Get( Expression<Func<TEntity, bool>> filter = null, Func<IQueryable<TEntity>, IOrdenetworkingQueryable<TEntity>> orderBy = null, string includeProperties = "") { IQueryable<TEntity> query = _dbSet; if (filter != null) { query = query.Where(filter); } foreach (var includeProperty in includeProperties.Split (new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries)) { query = query.Include(includeProperty); } if (orderBy != null) { return orderBy(query).ToList(); } else { return query.ToList(); } } 

Siempre obtengo el error Input string was not in a correct format en la última regla ( return query.ToList() ).

Pero cuando miro el _dbSet después de la regla IQueryable<TEntity> query = _dbSet; ya da el error: There is already an open DataReader associated with this Connection which must be closed first.

Esto probablemente se debe a que quiero seleccionar de más de una tabla. ¿Pero cómo puedo arreglar esto? Traté de agregar MultipleActiveResultSets=True" a ConnectionString de esta manera:

 <connectionStrings> <add name="reuzzeCS" connectionString="server=localhost;uid=root;pwd=*****;Persist Security Info=True;database=reuzze;MultipleActiveResultSets=True"" providerName="MySql.Data.MySqlClient" /> 

Pero eso me dio el error de que la palabra key no existe, porque trabajo con MySql.Data.MySqlClient …

La consulta ejecutada es:

{SELECCIONE Extent1 . entity_id , Extent1 . entity_title , Extent1 . entity_description , Extent1 . entity_starttime , Extent1 . entity_endtime , Extent1 . entity_instantsellingprice , Extent1 . entity_shippingprice , Extent1 . entity_condition , Extent1 . entity_views , Extent1 . entity_created , Extent1 . entity_modified , Extent1 . entity_deleted , Extent1 . user_id , Extent1 . region_id , Extent1 . category_id DE entities AS Extent1 }

Pero cuando quiere ejecutar la consulta y quiero expandir los resultados, There is already an open DataReader associated with this Connection which must be closed first el error. There is already an open DataReader associated with this Connection which must be closed first

EDITAR:
Mi repository completo:

 using System; using System.Collections.Generic; using System.Data; using System.Data.Entity; using System.Linq; using System.Linq.Expressions; using System.Text; using System.Threading.Tasks; namespace App.Data.orm.repositories { // REPO FROM TEACHER public class GDMRepository<TEntity> where TEntity : class { internal GDMContext _context; internal DbSet<TEntity> _dbSet; public GDMRepository(GDMContext context) { this._context = context; this._dbSet = _context.Set<TEntity>(); } public virtual IEnumerable<TEntity> Get( Expression<Func<TEntity, bool>> filter = null, Func<IQueryable<TEntity>, IOrdenetworkingQueryable<TEntity>> orderBy = null, string includeProperties = "") { IQueryable<TEntity> query = _dbSet; if (filter != null) { query = query.Where(filter); } foreach (var includeProperty in includeProperties.Split (new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries)) { query = query.Include(includeProperty); } if (orderBy != null) { return orderBy(query).ToList(); } else { return query.ToList(); } } public virtual TEntity GetByID(object id) { return _dbSet.Find(id); } public virtual void Insert(TEntity entity) { _dbSet.Add(entity); } public virtual void Delete(object id) { TEntity entityToDelete = _dbSet.Find(id); Delete(entityToDelete); } public virtual void Delete(TEntity entity) { if (_context.Entry(entity).State == EntityState.Detached) { _dbSet.Attach(entity); } _dbSet.Remove(entity); } public virtual void Update(TEntity entity) { _dbSet.Attach(entity); _context.Entry(entity).State = EntityState.Modified; } } } 

Clase GDMContext:

 using App.Data.orm.mappings; using System; using System.Collections.Generic; using System.Data.Entity; using System.Data.Entity.ModelConfiguration.Conventions; using System.Linq; using System.Text; using System.Threading.Tasks; namespace App.Data.orm { public class GDMContext:DbContext { public GDMContext() : base("reuzzeCS") { } protected override void OnModelCreating(DbModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); //REMOVE STANDARD MAPPING IN ENTITY FRAMEWORK modelBuilder.Conventions.Remove<PluralizingTableNameConvention>(); //REGISTER MAPPERS modelBuilder.Configurations.Add(new UserMapping()); modelBuilder.Configurations.Add(new PersonMapping()); modelBuilder.Configurations.Add(new RoleMapping()); modelBuilder.Configurations.Add(new EntityMapping()); modelBuilder.Configurations.Add(new MediaMapping()); modelBuilder.Configurations.Add(new BidMapping()); modelBuilder.Configurations.Add(new CategoryMapping()); modelBuilder.Configurations.Add(new AddressMapping()); modelBuilder.Configurations.Add(new RegionMapping()); modelBuilder.Configurations.Add(new MessageMapping()); } } } 

Mi entidad Modelo:

 public class Entity { public Int64 Id { get; set; } [Requinetworking(ErrorMessage = "Title is requinetworking")] [StringLength(255)] [DisplayName("Title")] public string Title { get; set; } [Requinetworking(ErrorMessage = "Description is requinetworking")] [DisplayName("Description")] public string Description { get; set; } [Requinetworking] public DateTime StartTime { get; set; } [Requinetworking] public DateTime EndTime { get; set; } /*[Requinetworking(ErrorMessage = "Type is requinetworking")] [StringLength(16)] [DisplayName("Type")] public string Type { get; set; }*/ [Requinetworking] public decimal InstantSellingPrice { get; set; } public Nullable<decimal> ShippingPrice { get; set; } public Condition? Condition { get; set; } public Nullable<Int64> Views { get; set; } [Requinetworking] public DateTime CreateDate { get; set; } public Nullable<DateTime> ModifiedDate { get; set; } public Nullable<DateTime> DeletedDate { get; set; } public Int32 UserId { get; set; } public Int32 RegionId { get; set; } public Int16 CategoryId { get; set; } public virtual User User { get; set; } public virtual Region Region { get; set; } public virtual Category Category { get; set; } //public virtual ICollection<Category> Categories { get; set; } public virtual ICollection<User> Favorites { get; set; } public virtual ICollection<Bid> Bids { get; set; } public virtual ICollection<Media> Media { get; set; } } public enum Condition { New = 1, Used = 2 } 

Mi map de entidades:

 internal class EntityMapping : EntityTypeConfiguration<Entity> { public EntityMapping() : base() { this.ToTable("entities", "reuzze"); this.HasKey(t => t.Id); this.Property(t => t.Id).HasColumnName("entity_id").HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); this.Property(t => t.Title).HasColumnName("entity_title").IsRequinetworking().HasMaxLength(255); this.Property(t => t.Description).HasColumnName("entity_description").IsRequinetworking(); this.Property(t => t.StartTime).HasColumnName("entity_starttime").IsRequinetworking(); this.Property(t => t.EndTime).HasColumnName("entity_endtime").IsRequinetworking(); //this.Property(t => t.Type).HasColumnName("entity_type").IsRequinetworking(); this.Property(t => t.InstantSellingPrice).HasColumnName("entity_instantsellingprice").IsRequinetworking(); this.Property(t => t.ShippingPrice).HasColumnName("entity_shippingprice").IsOptional(); this.Property(t => t.Condition).HasColumnName("entity_condition").IsRequinetworking(); this.Property(t => t.Views).HasColumnName("entity_views").IsOptional(); this.Property(t => t.CreateDate).HasColumnName("entity_created").IsRequinetworking().HasDatabaseGeneratedOption(DatabaseGeneratedOption.Computed); this.Property(t => t.ModifiedDate).HasColumnName("entity_modified").IsOptional(); this.Property(t => t.DeletedDate).HasColumnName("entity_deleted").IsOptional(); this.Property(t => t.UserId).HasColumnName("user_id").IsRequinetworking(); this.Property(t => t.RegionId).HasColumnName("region_id").IsRequinetworking(); this.Property(t => t.CategoryId).HasColumnName("category_id").IsRequinetworking(); //FOREIGN KEY MAPPINGS this.HasRequinetworking(t => t.User).WithMany(p => p.Entities).HasForeignKey(f => f.UserId).WillCascadeOnDelete(false); this.HasRequinetworking(t => t.Region).WithMany(p => p.Entities).HasForeignKey(f => f.RegionId); this.HasRequinetworking(t => t.Category).WithMany(p => p.Entities).HasForeignKey(f => f.CategoryId); //MANY_TO_MANY MAPPINGS this.HasMany(t => t.Favorites) .WithMany(t => t.Favorites) .Map(mc => { mc.ToTable("favorites"); mc.MapLeftKey("entity_id"); mc.MapRightKey("user_id"); }); } } 

Enlace a la image stacktrace!

ACTUALIZAR:

  • base {SELECCIONE Extent1 . entity_id , Extent1 . entity_title , Extent1 . entity_description , Extent1 . entity_starttime , Extent1 . entity_endtime , Extent1 . entity_instantsellingprice , Extent1 . entity_shippingprice , Extent1 . entity_condition , Extent1 . entity_views , Extent1 . entity_created , Extent1 . entity_modified , Extent1 . entity_deleted , Extent1 . user_id , Extent1 . region_id , Extent1 . category_id FROM entities AS Extent1 } System.Data.Entity.Internal.Linq.InternalQuery {System.Data.Entity.Internal.Linq.InternalSet}

Tu problema es

Creo que el conector MySql probablemente no admite varios sets de resultados activos y, por eso, la configuration en la cadena de connection no te ayudó.

Por favor, intente de esta manera en lugar de su código

Editar:

 query.Include("User").Include("Region").Include("Category").ToList(); 

Avísame si recibes el mismo error después de este cambio.

Actualizar:

He cambiado algo para ti. Usa este código en lugar de tu método.

  public virtual IEnumerable<TEntity> Get( Expression<Func<TEntity, bool>> filter = null, Func<IQueryable<TEntity>, IOrdenetworkingQueryable<TEntity>> orderBy = null, string includeProperties = "") { IQueryable<TEntity> query = _dbSet; if (filter != null) { query = query.Where(filter); } if (orderBy != null) { return orderBy(query.Include("User").Include("Region").Include("Category").ToList()).ToList(); } else { return query.Include("User").Include("Region").Include("Category").ToList(); } } 

Actualización 2:

No se trata de cerrar la connection. EF gestiona la connection correctamente. Mi comprensión de este problema es que hay múltiples commands de recuperación de datos ejecutados en una sola connection (o un solo command con selects múltiples) mientras se ejecuta el siguiente DataReader antes de que el primero haya completado la lectura. La única forma de evitar la exception es permitir múltiples DataReaders nesteds = activar MultipleActiveResultSets. Otro escenario en el que esto siempre sucede es cuando itera a través del resultado de la consulta (IQueryable) y activará la carga diferida para la entidad cargada dentro de la iteración.

Y el desbordamiento de la stack tiene mucha gente tiene las soluciones para su pregunta

1: Entity Framework: ya hay un DataReader abierto asociado a este command

2: Cómo evitar "Ya hay un DataReader abierto asociado a esta connection que debe cerrarse primero". en el conector de MySql / net?

3: Error: ya hay un DataReader abierto asociado con este command que debe cerrarse primero

y mi consejo personal para, creo que no pasaste más time para este error, porque te da time y energía, y puedes hacerlo mediante consultas manuales. Por favor, intente de diferentes maneras.

No es necesario dividir y formatear las consultas para evitar input string was not correct format error de input string was not correct format

Puede hacerlo de esta manera en lugar de return query.ToList();

 return _dbSet.Users .Include(x => x.Region) .Include(x => x.Category).ToList(); 

Creo que puedes hacerlo usando mis enlaces SO arriba.

Y mi pregunta principal es:

Entity Framework puede soportar el concepto de ORM, entonces, ¿por qué no lo intentas de esta manera ?. Puede cambiar la idea de usar el concepto de ORM. Se puede resolver este problema. Este es un enlace para eso y ve este tutorial

ACTUALIZAR

OK, entonces desde su rastro de stack parece que el " open DataReader associated ...blah " fue un problema. Quizás fue Visual Studio y su depurador visual intellisense tratando de mostrarle los valores contenidos en su dbset pero una connection aún estaba abierta o algo así.

Para mí, parece que MySqlDatareader de EF está haciendo su trabajo de enumerar los resultados y asignarlos a POCO.

Tal vez hay una columna que es un varchar (..) o algo por el estilo en una tabla en su Base de datos, y en su POCO, su propiedad mapeada es de oftype(Int32) . Entonces, si hay una cadena vacía o un valor que no es un número en la database, creo que una Input string was not in a correct format exception cuando se intenta convertir un valor de cadena vacía o nula a una Int. Solo intenté esto ahora para ver:

enter image description here


Creo que el problema es que MySql no es compatible con MARS y tal vez tampoco respalde Lazy Loading . Si bien no pude encontrar nada oficial para decir que este era el caso, encontré algunas publicaciones con el mismo problema que tú.

http://www.binaryforge-software.com/wpblog/?p=163

¡Problema de MySQL + Code First + Lazy Load!

http://forums.mysql.com/read.php?38,259559,267490

Ahora, hasta hace bastante poco, pensé que llamar a ToList() en un ToList() los resultados en la memory y que las properties de navigation no serían LazyLoaded , esto no es estrictamente cierto. Aunque el resultado se mantendrá en la memory, las properties de navigation virtuales de ese resultado seguirán cargadas de forma lenta si intenta acceder a ellas.

En un alto nivel, LazyLoading funciona porque el marco de entidades overrides tus properties de navigation "virtuales" y usa su propia implementación para cargar entidades desde la database.

Supongo que en su Vista o en otro lugar de su código debe acceder a una propiedad que no ha cargado explícitamente utilizando un Include . Creo que EF puede estar tratando de hacer esto en una sola connection y es por eso que ves:

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

Desactivaría Lazyloading haciendo lo siguiente:

 public class GDMContext:DbContext { public GDMContext() : base("reuzzeCS") { base.Configuration.LazyLoadingEnabled = false; } } 

Espero que esto ayude.

Según su rastro de stack, el marco parece tener un problema al convertir una cadena en un integer. Para citar otra respuesta SO , "EF arroja un error cada vez que configura un tipo en el model que es diferente de la tabla".

Tienes pocas opciones.

Si está utilizando un primer enfoque de código, le sugiero que regenere su database.

Si está utilizando un enfoque de "segundo código" (que asigna las tablas de su database a las classs de POCO), le sugiero que regenere su database.

Si no ha tenido suerte con ninguno de los anteriores, al less puede limitar qué columna está teniendo el problema al probar cada una de sus columnas basadas en integers de esta manera:

 public ActionResult Index() { var model1 = this.UnitOfWork.EntityRepository.Get( includeProperties: "category_id"); // Did that produce an error? If not, try another column: var model2 = this.UnitOfWork.EntityRepository.Get( includeProperties: "region_id"); // etc. // If you get to your original code, then try testing other columns var model = this.UnitOfWork.EntityRepository.Get(); return View(model); } 

¿Qué pasa si lo anterior no funciona? Podría haber un problema con su cadena de connection, como se menciona en esta respuesta SO . Esta es probablemente una posibilidad remota, dado que su traza de stack no parece tropezar con la creación de una connection, pero vale la pena señalar en su cadena de connection para MARS que parece haber una comilla doble adicional (aunque estoy seguro de que es probable solo un error de transcripción). En cualquier caso, si no puede hacer que ninguna consulta funcione, asegúrese de que su cadena de connection se vea normal, como la siguiente:

 <connectionStrings> <add name="reuzzeCS" connectionString= "server=localhost;database=Reuzze;User Id=root;password=P4ssw0rd" providerName="MySql.Data.MySqlClient" /> </connectionStrings> 

¿Qué pasa si lo anterior no funciona? Compruebe que su versión de EntityFramework funciona bien con su versión de MySQL.

Simplifiquemos el problema. Ningún cuerpo puede ayudarlo a less que lo desee. En primer lugar, debo mencionar que MultipleActiveResultSets=True en su connectionString según MSDN :

Es una característica que funciona con SQL Server para permitir la ejecución de lotes múltiples en una sola connection. Cuando MARS está habilitado para su uso con SQL Server, cada object de command utilizado agrega una session a la connection.

¡Entonces eso no funciona con MySQL!

Creo que debes especificar el número de puerto en tu connection como:

 <connectionStrings> <add name="reuzzeCS" connectionString="server=localhost;uid=root;pwd=*****;Persist Security Info=True;database=reuzze;" providerName="MySql.Data.MySqlClient" /> </connectionStrings> 

Editar: Y, necesita utilizar Connector / Net que es un controller ADO.NET totalmente administrado para MySQL en esta página . Funciona para la mayoría de los escenarios básicos de interacción de db. También tiene integración básica de Visual Studio. De acuerdo con esta página, también necesitas un conector.

Espero ser útil. Saludos.