【问题标题】:Entity Framework runtime error - There is already an open DataReader associated with this Command which must be closed first实体框架运行时错误 - 已经有一个打开的 DataReader 与此命令关联,必须先关闭
【发布时间】:2020-09-29 12:39:58
【问题描述】:

我有一个包含以下模型和上下文的示例应用程序-

   public class Department
   {
     public int Id { get; set; }
     public string Name { get; set;}
     public virtual ICollection<Student> Students { get; set; }
   }

   public class Student
   {
     public int Id { get; set; }

     public string Name { get; set; }

     public virtual Department Department { get; set; }
   }
 public class TestContext : DbContext
{
    public DbSet<Student> Students { get; set; }
    public DbSet<Department> Departments { get; set; }
}

下面是 progarm.cs 代码。当我调试并且调试器到达 - foreach 块内的 Consol.WriteLine 方法时,我收到错误 - 已经有一个打开的 DataReader 与此命令关联,必须先关闭。这是为什么。到达 foreach 代码时,一旦打开连接,上下文不应自动关闭。

    class Program
{
    static void Main(string[] args)
    {
        using (var context = new TestContext())
        {
            var students = context.Students.Where(s => s.Id == 1);

            foreach (var student in students)
            {
                Console.WriteLine("Student : {0} - Department {1}", student.Name, student.Department.Name);
            }

            Console.ReadLine(); 
        }
    }

【问题讨论】:

标签: c# entity-framework entity-framework-6 dbcontext


【解决方案1】:

为了回答您的问题,您将TestContext 包裹在using 语句中,这意味着TestContext 将保持打开状态直到using 语句结束。

您的初始调用本质上是一个查询,只有在您的 foreach 循环被命中时才会执行:

var students = context.Students.Where(s => s.Id == 1);

这是导致错误的原因。即,它会导致对 DataReader 的多个查询不允许这样做。

@Arman 是正确的:.ToList() 将解决您的问题,因为正在执行查询以在 foreach 循环之前将所有学生都放到一个列表中。显然,这个问题有很多解决方案。可能最常见的是在您的连接字符串上将MARS (Multiple Active Result Sets) 设置为true;即:

Server={myServer};Initial Context={myDb};MultipleActiveResultSets=True;…

这将允许多个打开DataReaders

【讨论】:

    【解决方案2】:

    由于在 foreach 循环中出现此问题:student.Department.Name

    实际上,这里有一个与 foreach 循环关联的 DataReader 和一个与加载 Department 关联的 DataReader

    以这种方式更改检索,您的问题应该得到解决:

    var students = context.Students.Where(s => s.Id == 1).Include(s => s.Department).ToList();
    

    【讨论】:

    • 使用添加的包含,您可能不需要显式调用ToList
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-09-02
    • 1970-01-01
    • 1970-01-01
    • 2011-08-29
    相关资源
    最近更新 更多