EntityFramework 4.5 - 即使在使用Include后仍然会获得ObjectDisposedException

时间:2014-06-27 17:35:41

标签: c# entity-framework

我正面临异常即使在使用Include方法之后,ObjectContext实例也已被处置并且不能再用于需要连接的操作

这里是检索实体的函数:

    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()会在关闭之前实例化对象列表和include中的相关对象。

  

有人能指出我做错了什么吗?   对不起,我的问题不明确。我明白包含在使用的括号内抛出异常的行是可行的,但我不知道为什么包含不起作用

谢谢!

2 个答案:

答案 0 :(得分:3)

尝试更改

    // 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);

答案 1 :(得分:1)

您的问题有三种解决方案。这些来自此链接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语句,它将在第一次调用时加载它(它不会复制对数据库的访问,但它会一次提取更多数据)。 / p>

第三个解决方案是避免依赖Lazy Loading,这可能是一个很好的方法。它是显式加载技术,它要求您指定要在指定实体上加载EquipmentSection相关实体。

我希望这些解释可以帮到你。

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