实体类中有外关键字关联另一张表导致查询出现已有打开的与此 Command 相关联的 DataReader,必须首先将它关闭的解决

今天在做一个返回json方法时出现了已有打开的与此 Command 相关联的 DataReader,必须首先将它关闭的错误。代码如下:

public JsonResult GetCompletedSimulation()
        {
            var service = new ExamMainService();
            var list = service.Get(m =>m.UserId== Member.Id && m.Name.Contains("Simulation")).OrderByDescending(m => m.ExamTime);
            return Json(list);
        }

感觉瞬间凌乱了。因为出现这个问题通常是因为循环嵌套才会造成这样的问题。这就一条linq语句,查询出来直接返回了,怎么会出现这种问题。先是怀疑是因为Member.Id 的问题,这是一个封装的属性,此属性执行了查询语句。因此先把其摘出来。再执行。代码如下:

string userid = Member.Id;
 var list = service.Get(m =>m.UserId== userid  && m.Name.Contains("Simulation")).OrderByDescending(m => m.ExamTime);

然后执行,仍然报这个错。不是这里的问题,那会是哪里的。无奈service.get语句增加了tolist方法。

var list = service.Get(m =>m.UserId== userid && m.Name.Contains("Simulation")).OrderByDescending(m => m.ExamTime).ToList();

这不报错了。可是,为什么会出现这种情况。在项目中好多这样的语句根本不需要tolist的。

于是继续查找原因,在fiddler的输出中发现了ExamLists,突然想起这个查询的ExamMain表是和ExamList表相关联的,是外关键字关联。一对多的关系

 public partial class ExamMain
    {
       ...
        [ForeignKey("ExamMainGID")]
        public virtual ICollection ExamLists { get; set; }
    }

估计是这里的问题。

通过大量的扒资料,发觉 service.Get(m =>m.UserId== userid && m.Name.Contains("Simulation")).OrderByDescending(m => m.ExamTime) 最后生成的是 IQueryable 对象。IQueryable 对象EF内部机制是使用DataReader读取数据对象。DataReader对象的读取在一个数据连接中每次

只允许打开一个。由于ExmaMain关联了ExamList对象,对Examlist对象读取的时候也用到了这个连接,这就导致了此问题。ToList()后就把数据对象

存到了内存,与数据库就没关系了。因此ToList()后就不会出现已有打开的与此 Command 相关联的 DataReader,必须首先将它关闭的错误

你可能感兴趣的:(asp.net,MVC,C#)