【问题标题】:'The operation cannot be completed because the DbContext has been disposed.''操作无法完成,因为 DbContext 已被释放。'
【发布时间】:2020-01-30 05:31:39
【问题描述】:
public ActionResult Index(FormModel form)
{
    using (DBModels db = new DBModels())

    {
        var clients = from c in db.Clients
                      select c;

        if (!String.IsNullOrEmpty(form.SearchString))
        {
            clients = clients.Where(s => s.Full_Name.Contains(form.SearchString) || s.Class.Contains(form.SearchString)
            || s.Membership_Type.Contains(form.SearchString) || s.Membership_Type.Contains(form.SearchString) ||
            s.Notes.Contains(form.SearchString) || s.ClientID.Equals(form.SearchString));
        }
             if (form.IsChecked != null)
              {
                  clients = clients.Where(t => t.Paid == form.IsChecked);
              }
        return View(clients);

    }
}  

不明白为什么会发生此错误。我添加了一个搜索框来搜索数据库。我还添加了一个复选框来显示未付费客户。当我改变

return View(clients); 

返回

return View(db.Client.ToList()); 

它有效,但这是我试图避免的,因为它显示了所有列表,而不是显示 SearchString 中的那些的“客户”变量。

【问题讨论】:

  • 当您的视图尝试访问列表时,DBModel 已被释放,因此您的错误发生了。您可以通过多种方式解决此问题。通过更改 db 变量的生命周期...使其成为成员,或者您可以更改控制器和视图以传递所需的参数以在控制器中进行过滤。在不知道视图中发生了什么的情况下,很难提供答案

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


【解决方案1】:

clients 是一个 IQueryable。在请求第一次迭代之前,IQueryable 不会枚举它的值。到那时,你的 DbContext 已经被释放了,所以枚举会抛出异常。

要解决这个问题,请使用类似

using (DBModels db = new DBModels())
{
    var clients = Enumerable.Empty<Client>();

    if (!String.IsNullOrEmpty(form.SearchString))
    {
        clients = db.Clients.Where(s => s.Full_Name.Contains(form.SearchString) || s.Class.Contains(form.SearchString)
        || s.Membership_Type.Contains(form.SearchString) || s.Membership_Type.Contains(form.SearchString) ||
        s.Notes.Contains(form.SearchString) || s.ClientID.Equals(form.SearchString));
    }

    if (form.IsChecked != null)
    {
        clients = clients.Where(t => t.Paid == form.IsChecked);
    }

    return View(clients.ToList());
}

理论上,在调用 ToList() 之前,您应该避免调用数据库,但是自从我走这条路以来已经有一段时间了。相反,我建议使用来自 LinqKit 的PredicateBuilder 来构建一个完全针对数据库运行的查询,如下所示:

using (DBModels db = new DBModels())
{
    var predicate = PredicateBuilder.New<Client>(true);

    if (!String.IsNullOrEmpty(form.SearchString))
    {
        predicate.And(s => s.Full_Name.Contains(form.SearchString) || s.Class.Contains(form.SearchString)
        || s.Membership_Type.Contains(form.SearchString) || s.Membership_Type.Contains(form.SearchString) ||
        s.Notes.Contains(form.SearchString) || s.ClientID.Equals(form.SearchString));
    }

    if (form.IsChecked != null)
    {
        predicate.And(t => t.Paid == form.IsChecked);
    }

    return View(db.Clients.Where(predicate).ToList());
}

【讨论】:

    【解决方案2】:

    IQueryable 类型的数据结构主要用于迭代目的,在使用 ToList 之前这些不会产生价值。 这就是为什么在处置 dbcontext 后不评估您的对象的原因。

    【讨论】:

      猜你喜欢
      • 2016-05-28
      • 1970-01-01
      • 1970-01-01
      • 2021-03-01
      • 2015-04-03
      • 2015-08-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多