【问题标题】:EntityFramework 4.5 - Still get ObjectDisposedException even after using IncludeEntityFramework 4.5 - 即使在使用 Include 之后仍然会得到 ObjectDisposedException
【发布时间】:2014-06-27 17:35:40
【问题描述】:

我正面临异常ObjectContext 实例已被释放,即使在使用 Include 方法后也无法再用于需要连接的操作

这里是检索实体的函数:

    public List<Entity.CapacityGrid> SelectByFormula(string strFormula, int iVersionId)
    {
        // declaration
        List<Entity.CapacityGrid> oList;

        // retrieve ingredients
        oList = (from Grid in _Dc.CapacityGrid.Include("EquipmentSection")
                             join Header in _Dc.CapacityHeader
                             on Grid.HeaderId equals Header.HeaderId
                             where Header.Formula == strFormula
                             && Header.VersionId == iVersionId
                             select Grid).ToList();

        // return
        return oList;

这里是函数的用法:

        // retrieve ingredient quantity by equipement
        using (Model.CapacityGrid oModel = new Model.CapacityGrid(Configuration.RemoteDatabase))
            oQuantity = oModel.SelectByFormula(strFormulaName, iVersionId);

        // code to throw the exception
        var o = (oQuantity[0].EquipmentSection.TypeId);

我知道使用正在关闭连接。我认为 ToList() 将在关闭之前实例化包含中的对象列表和相关对象。

谁能指出我做错了什么? 抱歉,我的问题不清楚。我确实知道在 using 的括号内包含引发异常的行是有效的,但我不明白 为什么包含不起作用

谢谢!

【问题讨论】:

  • ToList 之前尝试.Include,如下所示:.Include(g =&gt; g.Equipmentsection).ToList()
  • 你好 DavidG,不知何故,没有包含函数。我写了这行代码并收到消息:System.Linq.IQueryable' 不包含“包含”的定义,并且没有扩展方法“包含”接受类型的第一个参数。谢谢!
  • 我假设_Dc.CapacityGridDbSet?如果是这样,那么 Include 确实应该起作用。你检查生成的 SQL 了吗?
  • @SebastienDErrico:您是否包含了 System.Data.Entity 命名空间?这是设置Include 扩展方法的地方。
  • 你说得对,我错过了对 System.Data.Entity 的使用

标签: c# entity-framework


【解决方案1】:

尝试改变

    // retrieve ingredient quantity by equipement
    using (Model.CapacityGrid oModel = new Model.CapacityGrid(Configuration.RemoteDatabase))
   {  // <-- **add these**
        oQuantity = oModel.SelectByFormula(strFormulaName, iVersionId);

    // code to throw the exception
    var o = (oQuantity[0].EquipmentSection.TypeId);
   } // <-- **add these**

参考:http://msdn.microsoft.com/en-us/library/yh598w02.aspx

在没有{} 的情况下使用,连接被安排在第一行之后。因为实体框架使用表达式树(这意味着在它真正需要它之前不会执行请求),所以您的查询发生在var o = (oQuantity[0].EquipmentSection.TypeId);

【讨论】:

  • 还应该把oQuantity放在using语句中。
  • 这并不能真正回答问题。
  • 怎么办?“ObjectContext 实例已被释放,不能再用于需要连接的操作”。对象正在被处理——用适当的大括号括起来代码将消除这个问题。
  • 不,问题是为什么 Include 没有做它显然应该做的事情。不是如何解决它。
  • 在问题中我看不到这不是答案 - 请详细说明。对象 oModel 被释放——一旦它被释放,试图对它做任何事情都会抛出该异常。将它包裹在大括号中将消除该问题,如果 .Include() 仍然存在问题,它们将是新的 - 并且是一个不同的问题。我错过了什么吗?
【解决方案2】:

您的问题有三种解决方案。这些来自此链接here,是链接到相关实体的三种方式。第一个解决方案是您一直在使用的延迟加载解决方案。只需将您的代码修改为此即可。它抛出异常的原因是因为延迟加载仅在您需要时发生。当您只需要在少数实体上加载相关实体时,这是一个很好的解决方案。

// retrieve ingredient quantity by equipement
using (Model.CapacityGrid oModel = new Model.CapacityGrid(Configuration.RemoteDatabase))
{
    oQuantity = oModel.SelectByFormula(strFormulaName, iVersionId);

    // Lazy-load occurs here, so it needs to have access to the
    // context, hence why it is in the using statement.
    var o = (oQuantity.First().EquipmentSection.TypeId);
}

第二种解决方案是使用急切加载(正如@DavidG 所建议的那样)。因为您只加载找到的第一个实体的相关实体,所以我不建议您在您的情况下使用它,因为它会加载您所有 oQuantity 实体的 EquipmentSection 实体。在您的 SelectByFormula 方法中,使用相关链接中所示的 Include 语句,它将在第一次调用时加载它(它不会重复对数据库的访问,但它会一次提取更多数据)。

第三种解决方案是避免依赖延迟加载,这是一个很好的方法。这是显式加载技术,需要您指定要在指定实体上加载EquipmentSection 相关实体。

希望这些解释对你有所帮助。

此外,您可能需要考虑在 SelectByFormula 方法上返回 IQueryable。这样,如果您必须过滤请求,例如使用 First() 方法仅获取第一次出现的请求,您就不会只为一个实例提取所有内容。

【讨论】:

  • 不错的答案,但我不同意你不使用急切加载的说法。在大多数情况下,延迟加载不会给您带来任何额外的好处,实际上会使您的应用程序变慢。无论如何,我要 +1。
  • 我的回答不够清楚。我指定在这种情况下我不会使用它,因为他加载了与公式对应的所有实体,然后只取第一项的相关实体的值。在这种情况下,急切加载可能只会加载比延迟加载或显式加载更多的数据。我确定了答案。
  • 添加 System.Data.Entity 并在链接中显示的 .ToList 之前移动包含解决了我的问题,而无需移动 using 子句的括号。谢谢!
猜你喜欢
  • 2016-12-13
  • 2016-08-15
  • 2019-06-30
  • 2018-04-27
  • 1970-01-01
  • 2014-07-31
  • 1970-01-01
  • 1970-01-01
  • 2019-03-03
相关资源
最近更新 更多