【问题标题】:There is already an open DataReader associated with this Connection which must be closed first + asp.net mvc已经有一个与此连接关联的打开的 DataReader 必须先关闭 + asp.net mvc
【发布时间】:2014-01-08 16:50:09
【问题描述】:

我有一个 mysql 数据库,其中有一个 entites 表,其中包含多个字段,例如 entity_title、entity_description...。表中还有 3 个外键 user_idregion_idcategory_id

在我的索引视图中,我想在表格中显示所有实体(显示标题、描述、...、用户名、区域名称和类别名称)。

这就是我在控制器中所做的:

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

在我的存储库中,我这样做:

public virtual IEnumerable<TEntity> Get(
    Expression<Func<TEntity, bool>> filter = null,
    Func<IQueryable<TEntity>, IOrderedQueryable<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();
    }
}

我总是在最后一条规则 (return query.ToList()) 上收到错误 Input string was not in a correct format

但是当我在规则 IQueryable&lt;TEntity&gt; query = _dbSet; 之后检查 _dbSet 时,它已经给出了错误:There is already an open DataReader associated with this Connection which must be closed first.

这可能是因为我想从多个表中进行选择。但是我该如何解决这个问题?我尝试将 MultipleActiveResultSets=True" 添加到我的 ConnectionString 中,如下所示:

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

但这给了我关键字不存在的错误,因为我使用的是 MySql.Data.MySqlClient ..

执行的查询是:

{选择 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}

但是当他想执行查询并且我想扩展结果时,我得到错误There is already an open DataReader associated with this Connection which must be closed first

编辑:
我的完整存储库:

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

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

我的实体模型:

public class Entity
{
    public Int64 Id { get; set; }
    [Required(ErrorMessage = "Title is required")]
    [StringLength(255)]
    [DisplayName("Title")]
    public string Title { get; set; }
    [Required(ErrorMessage = "Description is required")]
    [DisplayName("Description")]
    public string Description { get; set; }
    [Required]
    public DateTime StartTime { get; set; }
    [Required]
    public DateTime EndTime { get; set; }
    /*[Required(ErrorMessage = "Type is required")]
    [StringLength(16)]
    [DisplayName("Type")]
    public string Type { get; set; }*/
    [Required]
    public decimal InstantSellingPrice { get; set; }
    public Nullable<decimal> ShippingPrice { get; set; }

    public Condition? Condition { get; set; }
    public Nullable<Int64> Views { get; set; }

    [Required]
    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
}

我的实体映射:

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").IsRequired().HasMaxLength(255);
        this.Property(t => t.Description).HasColumnName("entity_description").IsRequired();
        this.Property(t => t.StartTime).HasColumnName("entity_starttime").IsRequired();
        this.Property(t => t.EndTime).HasColumnName("entity_endtime").IsRequired();
        //this.Property(t => t.Type).HasColumnName("entity_type").IsRequired();
        this.Property(t => t.InstantSellingPrice).HasColumnName("entity_instantsellingprice").IsRequired();
        this.Property(t => t.ShippingPrice).HasColumnName("entity_shippingprice").IsOptional();
        this.Property(t => t.Condition).HasColumnName("entity_condition").IsRequired();
        this.Property(t => t.Views).HasColumnName("entity_views").IsOptional();
        this.Property(t => t.CreateDate).HasColumnName("entity_created").IsRequired().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").IsRequired();
        this.Property(t => t.RegionId).HasColumnName("region_id").IsRequired();
        this.Property(t => t.CategoryId).HasColumnName("category_id").IsRequired();

        //FOREIGN KEY MAPPINGS
        this.HasRequired(t => t.User).WithMany(p => p.Entities).HasForeignKey(f => f.UserId).WillCascadeOnDelete(false);
        this.HasRequired(t => t.Region).WithMany(p => p.Entities).HasForeignKey(f => f.RegionId);
        this.HasRequired(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");
            });
    }
}

Link to stacktrace image!

更新:

  • 基础 {SELECT 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}

【问题讨论】:

  • 您还有其他查询数据库的地方吗? MySQL 不服务器 MARS。您需要确保在开始新查询之前始终调用ToList(),以便执行查询。 (即:您不能使用 MySQL 一次执行多个查询)。
  • 我不这么认为,编辑了我的开始帖子,这可能是问题吗?
  • 在执行前查看'query',能看到生成的SQL吗?
  • 我可以看到查询但是当他执行它并且我想检查结果时,我收到错误已经有一个打开的 DataReader 与此连接关联,必须先关闭。 (更新开始发布)
  • 如果您直接运行该查询,它是否有效?

标签: mysql asp.net sql asp.net-mvc entity-framework


【解决方案1】:

更新

好的,所以从您的堆栈跟踪来看,“open DataReader associated ...blah”看起来像是一条红鲱鱼。也许那是 Visual Studio 及其 intellisense 视觉调试器试图向您显示 dbset 中包含的值,但连接仍然打开或类似的东西。

在我看来,EF 的 MySqlDatareader 正在完成枚举结果并将它们映射到 POCO 的工作。

也许在您的数据库中的表上有一列是 varchar(..) 或类似的东西,而在您的 POCO 上,它的映射属性是 oftype(Int32)。因此,如果数据库中有一个空字符串或一个不是数字的值,我相信当您尝试将 null 或空字符串值转换为 Int 时,应该会出现Input string was not in a correct format 异常。刚刚试了一下,看看:


我认为问题在于 MySql 不支持MARS,也许它也不支持Lazy Loading。虽然我找不到任何官方的说法,但我发现了一些与您有相同问题的帖子。

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

MySQL + Code First + Lazy Load problem !

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

直到最近,我还认为在 IQueryable 上调用 ToList() 会将结果加载到内存中,并且任何导航属性都不会是 LazyLoaded,这并不完全正确。虽然结果将被持久化到内存中,但如果您尝试访问该结果的任何虚拟导航属性,它们仍将被延迟加载。

在较高级别 LazyLoading 有效,因为实体框架 overrides 您的“虚拟”导航属性并使用其自己的实现从数据库加载实体。

我的猜测是,在您的视图或代码中的其他地方,您必须访问一个您没有使用Include 显式加载的属性。我的猜测是 EF 可能会尝试在单个连接上执行此操作,这就是您看到的原因:

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

我会通过执行以下操作来关闭延迟加载:

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

希望这会有所帮助。

【讨论】:

  • 好的...嗯,你能发布你的错误的堆栈跟踪吗?
  • 添加了堆栈跟踪链接到帖子!
  • 有没有办法找到导致问题的列?重新检查了我的模型/映射,找不到任何东西:/
  • 您是否能够使用映射配置建立您的表架构及其映射的 POCO?有点远射,但也许试试这个...msdn.microsoft.com/en-us/library/cc667410.aspx ?
【解决方案2】:

根据您的堆栈跟踪,框架在将字符串转换为整数时出现问题。引用另一个SO answer,“每次在模型中设置与表不同的类型时,EF 都会引发错误。”

您有几个选择。

如果您使用的是代码优先方法,我建议您重新生成数据库。

如果您使用“代码第二”方法(将数据库表映射到 POCO 类),那么我建议您重新生成数据库。

如果您对上述任何一项都不满意,您至少可以通过像这样测试每个基于整数的列来缩小出现问题的列:

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

如果上述方法不起作用怎么办?如this SO answer 中所述,您的连接字符串可能存在问题。这可能是一个长镜头,因为您的堆栈跟踪似乎并没有因为创建连接而绊倒,但值得注意的是在您的 MARS 连接字符串中似乎有一个额外的双引号(尽管我确信它可能是只是一个转录错误。)在任何情况下,如果您无法让任何查询正常工作,请确保您的连接字符串看起来正常,如下所示:

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

如果上述方法不起作用怎么办?检查您的 EntityFramework 版本是否与您的 MySQL 版本兼容。

【讨论】:

  • 我正在使用 fluent api 将我的模型映射到我的数据库。很奇怪,有时我会收到错误“输入字符串不正确”,有时会出现“已经存在......”。只有一张桌子我有问题..
  • 我可以给你一个链接到我在 github 上的存储库吗?如果你愿意,我可以付钱......我真的坚持这一点,这很重要
  • 在帖子中添加了我的实体模型 + 映射。
【解决方案3】:

让我们简化问题。除非您愿意,否则任何机构都无法帮助您。首先我必须根据MSDN在你的connectionString中提到MultipleActiveResultSets=True

是一项与 SQL Server 一起使用的功能,允许在单个连接上执行多个批处理。启用 MARS 以与 SQL Server 一起使用时,使用的每个命令对象都会向连接添加一个会话。

所以这不适用于 MySQL!

我认为您需要在您的 connectionString 中指定端口号,例如:

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

编辑: 而且,您需要使用 Connector/Net,它是 MySQL in this page 的完全托管的 ADO.NET 驱动程序。它适用于大多数基本的数据库交互场景。它还具有基本的 Visual Studio 集成。根据this page,你也需要连接器。

希望对你有用。问候。

【讨论】:

  • 感谢您的帮助,但添加端口号没有结果。
  • 在帖子中添加了我的实体模型 + 映射。
  • @nielsv 我添加了一些附加信息。也许有用。
【解决方案4】:

你的问题是

我认为 MySql 连接器可能不支持多个活动结果集,因此连接字符串中的设置对您没有帮助。

所以请尝试这种方式而不是你的代码

编辑:

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

如果您在此更改后遇到同样的错误,请告诉我。

更新:

我已经为您更改了一些东西请使用此代码而不是您的方法

 public virtual IEnumerable<TEntity> Get(
    Expression<Func<TEntity, bool>> filter = null,
    Func<IQueryable<TEntity>, IOrderedQueryable<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(); 
            }
        }

更新 2:

这不是关闭连接。 EF 正确管理连接。我对这个问题的理解是,在单个连接(或具有多个选择的单个命令)上执行了多个数据检索命令,而下一个 DataReader 在第一个完成读取之前执行。避免该异常的唯一方法是允许多个嵌套的 DataReaders = 打开 MultipleActiveResultSets。经常发生这种情况的另一种情况是,当您迭代查询结果 (IQueryable) 时,您将触发迭代内加载实体的延迟加载。

堆栈溢出有很多人为您的问题找到了解决方案

1:Entity Framework: There is already an open DataReader associated with this Command

2:How to avoid "There is already an open DataReader associated with this Connection which must be closed first." in MySql/net connector?

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

我个人的建议是,我认为你不要为这个错误花更多的时间,因为时间和精力的腰部,你可以通过手动查询来做到这一点。所以请尝试不同的方法。

您不需要拆分和格式化查询来避免input string was not correct format 错误

你可以这样做而不是return query.ToList();

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

我认为您可以使用我上面的SO 链接来做到这一点。

我的主要问题是:

Entity Framework 可以支持 ORM 概念,那你为什么不尝试这种方式呢?你可以改变使用 ORM 概念的想法。或许可以解决这个问题。 This is a link for thatsee this tutorial

【讨论】:

  • 当我在 includeProperties 中添加所有外键时仍然出现错误。将我的实体模型 + 映射添加到帖子中。
  • @nielsv 嘿,不是外键,我是指外表。
  • 是的,补充说。是这样的吗: var model1 = this.UnitOfWork.EntityRepository.Get(includeProperties: "User, Region, Category"); (也单独尝试过)。实体模型可以在我的帖子中找到(你可以看到用户、地区、类别)
  • 但是构造函数已经分配了 null string includeProperties = "" 你用断点检查它是空还是空?
  • 试过了,还是报错“输入字符串的格式不正确。”
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-17
  • 2011-08-29
  • 2020-09-25
  • 2011-12-26
  • 1970-01-01
相关资源
最近更新 更多