LINQ to SQL在DataContext Dispose之后使用查询
本文关键字:之后 查询 Dispose DataContext to SQL LINQ | 更新日期: 2023-09-27 18:27:46
我正在为一个项目编写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到SQL?我知道我可以做一些类似.ToList
或.ToArray
的事情,但那样我就无法直接访问行属性,必须将其引用为问题[0]、问题[1]等,这甚至比在主项目中使用代码更混乱。
当您在using语句之外时,上下文将被自动释放,因此当实际枚举IEnumerable时,上下文已经被释放。
因此,您需要告诉Linq,当您在using
语句中时,它应该继续从DB中实际检索值。您可以通过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();
}
}
更改此项:
return problems;
到此:
return problems.ToList();
解释:
ToList()将遍历结果,并将它们全部拉入内存。因为这种情况发生在using语句中,所以您很好。因为它创建了一个列表,所以会返回您的值。
你可以通过其他方式来做到这一点。其基本思想是在using语句关闭之前实际检索结果。
另一种解决方案是避免使用using语句,创建一个迭代器,该迭代器拥有对象,并在迭代完最后一个项后处理它。
在退出using块之前,可以通过在IEnumerable上执行.ToList()来处理它。这将检索记录并填充列表。根据您的场景,这可能不是性能方面的最佳选择(您失去了延迟检索和额外过滤查询的可能性)
您必须在using子句中完成查询,即使用ToList()、First()或Count()等。
当前您正在返回查询,当您想要使用它时,由于数据库连接在使用前关闭,您将得到一个异常,只需执行:
return problems.AsEnumerable()
这是因为linq的执行方式有所不同。事实上,problems
对象只是一个查询,您应该将它转换为对象,以便在其他地方使用它。
您可能不想在using中使用上下文;问题是以后不能使用导航属性,因为当它试图加载相关数据时,您会遇到同样的"对象已处理"问题。您需要做的是让上下文存在,并直接返回结果。或者,在返回结果时,调用ToList()
,然后查询所有相关数据。