【问题标题】:MySqlException: There is already an open DataReader associated with this Connection which must be closed firstMySqlException:已经有一个打开的 DataReader 与此 Connection 关联,必须先关闭
【发布时间】:2020-09-25 08:02:51
【问题描述】:

我有一个 Index.cshtml 页面,其中一个表包含另一个表的外键。我在我的索引中添加了一个搜索功能,但是在搜索时,它会抛出这个异常:

MySqlException:已经有一个打开的 DataReader 与此 Connection 关联,必须先关闭。

我已经运行了调试器,看起来它在我的 ActionResult 中运行良好,但是当它尝试加载视图时,它在第 11 行崩溃。我怀疑这是因为该项目是我的数据库中的外键(在模型中表示为另一个类),因为我在其他索引中添加了搜索功能并且它可以工作。我已经注释了第 11 行和第 12 行,并且不再发生异常。

我来找你是因为即使我似乎找到了问题所在,但我真的不明白为什么会发生这个异常以及如何解决它。任何帮助将不胜感激。

PS : 我使用 Microsoft Docs 中的 this 代码来实现搜索功能。

1    @foreach (var item in Model)
2    {
3       <tr>
4            <td>
5                @Html.DisplayFor(modelItem => item.nom)
6            </td>
7            <td>
8                @Html.DisplayFor(modelItem => item.adresse)
9            </td>
10           <td>
11             //   @Html.DisplayFor(modelItem => item.responsable.prenom)
12             //   @Html.DisplayFor(modelItem => item.responsable.nom)
13           </td>
14           <td>
15                @Html.DisplayFor(modelItem => item.telephone)
16           </td>
17        </tr>
18    }

我的控制器

// GET: cinemas
public ActionResult Index(string searchString)
{
    IndexCinema_ViewModel viewModel = new IndexCinema_ViewModel();

    if (!String.IsNullOrEmpty(searchString))
    {
        viewModel.Cinemas = db.cinemas.Where(s => s.nom.Contains(searchString)
                || s.responsable.nom.Contains(searchString)
                || s.responsable.prenom.Contains(searchString));
        ViewBag.searchRequest = true;
    }
    else
    {
        viewModel.Cinemas = db.cinemas.Include(c => c.responsable);
        ViewBag.searchRequest = false;
    }

    ModelState.Clear();
    return View(viewModel);
}

【问题讨论】:

    标签: asp.net-mvc


    【解决方案1】:

    切勿在控制器操作之外发送IQueryable&lt;T&gt; 或非实体化IEnumerable&lt;T&gt;:注意in the example you linked to on Microsoft's website,代码如何调用ToList()之前返回View(model)

    您需要在 Action 中将查询具体化为 List&lt;T&gt;,以便可以安全地处理 DbContext 而不会留下悬空连接:

    viewModel.Cinemas = await db.cinemas
        .Include(c => c.responsable)
        .ToListAsync();
    

    【讨论】:

    • 我只在查询中添加了ToList();,因为我不熟悉异步方法,更重要的是不熟悉 MVC,因为它是我的第一个项目。我很想知道更多。您是否推荐我可以阅读的对我有帮助的资源?您还可以解释为什么在控制器外部发送 IEnumerable 是一种不好的做法吗?
    • @pensum 如果IEnumerable&lt;T&gt; 代表一个延迟评估的数据库查询,那么在IEnumerable&lt;T&gt;foreach.ToList() 方法中迭代之前不会执行该查询(例如) - 这意味着与查询关联的数据库连接将保持活动状态,并且在呈现视图之前无法被应用程序的其他部分使用 - 或者如果您的控制器(或 ASP.NET 本身)处理了您的DbContext 在呈现视图之前,查询根本无法执行。
    • @pensum 未评估的IQueryable&lt;T&gt; 的生命周期绑定到其父DbContext 的生命周期,方法是返回一个IQueryable&lt;T&gt;(即使它表示为IEnumerable&lt;T&gt;)你的 Controller Action 那么它可能比它的父 DbContext 寿命更长。像 Rust 这样的语言有用于表示对象生命周期的内置语法,我希望 C#' 有这样的特性,因为它在这样的情况下真的很有帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-01-17
    • 2011-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-23
    • 2013-07-18
    相关资源
    最近更新 更多