我正在为一个项目编写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]等。比主要项目中的代码色调更加混乱。
答案 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()
,然后再查询所有相关数据。