实体框架运行时错误 - 已经有一个打开的 DataReader 与此命令关联,必须先关闭
Posted
技术标签:
【中文标题】实体框架运行时错误 - 已经有一个打开的 DataReader 与此命令关联,必须先关闭【英文标题】:Entity Framework runtime error - There is already an open DataReader associated with this Command which must be closed first 【发布时间】: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();
【问题讨论】:
这能回答你的问题吗? There is already an open DataReader associated with this Command which must be closed first @marsze - 是的。 【参考方案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
以上是关于实体框架运行时错误 - 已经有一个打开的 DataReader 与此命令关联,必须先关闭的主要内容,如果未能解决你的问题,请参考以下文章