DataReader已经打开,必须关闭。我不明白

时间:2017-07-27 19:33:22

标签: c# asp.net-mvc linq session

我正在建模数据库以插入电影和电影。在影院上映。我知道剧院有很多会议,会议有电影和剧院。

public class Movie
    {
        public int MovieID { get; set; }
        public String MovieName { get; set; }
        public int Duration { get; set; }
        public int Rate { get; set; }
    }

public class Theater
    {
        public int TheaterID { get; set; }
        public String TheaterName { get; set; }
        public virtual ICollection<Session> Sessions { get; set; }
    }

public class Session
    {
        public int SessionID { get; set; }
        public int MovieID { get; set; }
        public int TheaterID { get; set; }
        public virtual Movie Movie { get; set; }
        public virtual Theater Theater { get; set; }
    }

我有一个接收一组会话的视图。在这个视图中,我使用foreach来显示剧院名称和所有电影:

这是来自控制器的代码:

 public ActionResult MoviesSessions(int id)
        {
            Theater theater = db.Theater.Find(id);
            ViewBag.TheaterName = Theater.TheaterName;
            var sessions = from s in db.Sessions where s.TheaterID == id orderby s.MovieID select s;
            return View(sessions);
        }

这是在视图中:

@{
        string theaterName = "";
        foreach (var item in Model)
        {
            if (theaterName != item.Theater.TheaterName)
            {
                theaterName = item.Theater.TheaterName;
                <tr>
                    <td>@Html.DisplayFor(modelItem => item.Movie.MovieName)</td>
                </tr>
            }
        }
    }

因为我使用item.Movie.MovieName我收到以下错误:

  

&#34;已经有一个与此命令关联的开放DataReader,必须先关闭它。&#34;

是否已在控制器查询中填充Movie对象?我不明白为什么我会收到此错误。这是我第一次使用asp.net

2 个答案:

答案 0 :(得分:1)

item.Movie属性是一个延迟查询,并尝试使用返回第一个查询结果的相同连接执行另一个数据库查询。某些数据库连接一次只允许一个活动的结果流,因此您必须首先读取所有行/实体,然后才能开始探索。您可以通过在查询(会话)上调用.ToList,然后将其传递给View函数来轻松完成此操作。此外,如果您使用的是SQL Server,则可以在连接字符串中设置“MultipleActiveResultSets = True”。

答案 1 :(得分:0)

您只需在连接字符串中设置MultipleActiveResultSets=true即可。由于您正在循环查询,因此您正在读取第一个对象,然后您正在尝试加载item.Theater.TheaterName,因为它具有导航属性并且它未包含在查询中,EF将触发第二个查询以加载{ {1}},因为之前的查询尚未完成,因为您的枚举未完成。如果MultipleActiveResultSet未设置为true,则会抛出错误。将其设置为true将允许EF在同一连接上打开多个打开的查询。

item.Theater.TheaterName

OR

其他方式是使用 connectionString="Data Source=MATT-PC\SQLEXPRESS;" + "Initial Catalog=Raise;Integrated Security=True;" + "MultipleActiveResultSets=true;" ToList

include

OR

 // .ToList() will force entire query to load and close data reader
 foreach(var m in Model.ToList()){
      ....
 }

推荐

 // since you are only interested in Theater, you could eager load 
 // Theater, this will cause EF to load Theater along with Movies in single
 // query
 foreach(var m in Model.Include("Theater")){
      ....
 }

许多人认为这会导致代码中的双重枚举,但这也会减少sql server上的开放查询时间,这有助于减少事务死锁和超时。在底层,SQL查询对整个枚举是开放的,在事务中,它肯定会损害SQL的性能。