LINQ to SQL在DataContext Dispose之后使用查询

时间:2012-03-13 20:34:57

标签: c# asp.net linq-to-sql

我正在为一个项目编写DLL,我刚开始使用LINQ to SQL并将所有方法移动到这个新的dll之后。我发现我不能访问DataContext,因为它被处理掉了,我理解为什么但我不确定如何查询我的主项目方法的结果如此:

我在DLL中的方法

 public static IEnumerable<Problem> GetProblemsNewest(int howMuch)
        {
            using (ProblemClassesDataContext context = new ProblemClassesDataContext())
            {
                var problems = (from p in context.Problems orderby p.DateTimeCreated select p).Take(howMuch);

                return problems;
            }
        }

致电:

IEnumerable<Problem> problems = ProblemsManipulation.GetProblemsNewest(10);
//Error can't acess it because it was disposed..

这只是第一种方法,我有更大的方法,所以我真的需要一种方法来做到这一点。必须有一种方法在DLL中使用LINQ to SQL?我知道我可以做.ToList.ToArray之类的事情,但后来我无法直接获取行属性,并且必须将其引用为问题[0],问题[1]等。比主要项目中的代码色调更加混乱。

6 个答案:

答案 0 :(得分:7)

在使用using语句之后,上下文会自动释放,因此当实际枚举IEnumerable时,上下文已经被释放。

因此,您需要告诉Linq它应该继续并在您的using语句内部实际检索数据库中的值。您可以通过ToList()ToArray(或其他人)完成此操作。

请参阅更新的代码:

public static IList<Problem> GetProblemsNewest(int howMuch)
{
    using (ProblemClassesDataContext context = new ProblemClassesDataContext())
    {
        var problems = (from p in context.Problems orderby p.DateTimeCreated select p).Take(howMuch);

        return problems.ToList();
    }
}

答案 1 :(得分:4)

改变这个:

return problems;

到此:

return problems.ToList();

解释

ToList()将迭代结果并将它们全部拉入内存。因为这发生在using语句中,你没问题。因为它会创建一个列表,所以会返回您的值。

您可以通过其他方式执行此操作。基本思想是在using语句关闭之前实际检索结果。

另一种解决方案是避免使用using语句,创建一个拥有该对象的迭代器,并在迭代过去最后一项时将其处理掉。

答案 2 :(得分:1)

您可以通过在退出using块之前对IEnumerable执行.ToList()来处理它。这将检索记录并填充列表。根据您的情况,这在性能方面可能不是最佳的(您将失去延迟检索和对查询进行额外过滤的可能性)

答案 3 :(得分:1)

你必须在using子句中完成查询,即使用ToList()或First()或Count()等...

答案 4 :(得分:1)

目前您返回查询,并且当您想要使用它时,因为数据库连接在您使用之前关闭,您将获得异常,只需执行:

return problems.AsEnumerable()

这是因为linq的deffered execution方式。实际上,您的problems对象只是查询,您应该将其转换为对象,以便在其他地方使用它。

答案 5 :(得分:0)

您可能不想在使用中使用上下文;问题是您以后不能使用导航属性,因为在尝试加载相关数据时,您将遇到相同的“对象处置”问题。您需要做的是让上下文生效,并直接返回结果。或者,当您返回结果时,请致电ToList(),然后再查询所有相关数据。