更新 - 答案显然是 DbLinq 没有实现 Dispose()
适本地。哦!
以下内容具有误导性 - 底线:DbLinq(目前)还不等同于 LinqToSql,正如我最初问这个问题时所假设的那样。谨慎使用!
我正在将存储库模式与 DbLinq 一起使用。我的存储库对象实现 IDisposable
, 和 Dispose()
方法只做一件事——调用 Dispose()
在 DataContext
上.每当我使用存储库时,我都会将其包装在 using
中 block ,像这样:
public IEnumerable<Person> SelectPersons()
{
using (var repository = _repositorySource.GetPersonRepository())
{
return repository.GetAll(); // returns DataContext.Person as an IQueryable<Person>
}
}
此方法返回 IEnumerable<Person>
,所以如果我的理解是正确的,直到 Enumerable<Person>
才真正查询数据库。被遍历(例如,通过将其转换为列表或数组或通过在 foreach
循环中使用它),如本例所示:
var persons = gateway.SelectPersons();
// Dispose() is fired here
var personViewModels = (
from b in persons
select new PersonViewModel
{
Id = b.Id,
Name = b.Name,
Age = b.Age,
OrdersCount = b.Order.Count()
}).ToList(); // executes queries
在这个例子中,Dispose()
在设置 persons
后立即被调用,这是一个 IEnumerable<Person>
,这是它唯一一次被调用。
那么,三个问题:
- 这是如何运作的?如何处置
DataContext
在DataContext
之后仍然在数据库中查询结果已经处置了吗? - 什么是
Dispose()
真的吗? - 我听说没有必要(例如,参见 this question )处理
DataContext
,但我的印象是这不是一个坏主意。有什么理由不处理 DbLinqDataContext
?
最佳答案
1 How does this work? How can a disposed DataContext still query the database for results after the DataContext has been disposed?
它不起作用。有些东西你没有给我们看。我猜要么是你的存储库类没有正确/在正确的时间处理 DataContext
,要么是你在每个类的末尾敷衍地写了 ToList()
查询,这完全否定了您通常获得的查询转换和延迟执行。
在测试应用中尝试以下代码,我保证你会抛出 ObjectDisposedException
:
// Bad code; do not use, will throw exception.
IEnumerable<Person> people;
using (var context = new TestDataContext())
{
people = context.Person;
}
foreach (Person p in people)
{
Console.WriteLine(p.ID);
}
这是最简单的可重现案例,它总是会抛出。另一方面,如果您改为编写 people = context.Person.ToList()
,则查询结果已经在 inside 中枚举了 using
阻止,我敢打赌你的情况就是这样。
2 What does Dispose() actually do?
除其他事项外,它设置了一个标志,指示 DataContext
已处理,在每个后续查询中检查该标志,并导致 DataContext
抛出 ObjectDisposedException
消息 Object name: 'DataContext accessed after Dispose.'。
如果 DataContext
打开并保持打开状态,它也会关闭连接。
3 I've heard that it is not necessary (e.g., see this question) to dispose of a DataContext, but my impression was that it's not a bad idea. Is there any reason not to dispose of a LinqToSql DataContext?
有必要Dispose
DataContext
,因为有必要Dispose
每隔一个 IDisposable
。如果未能处理 DataContext
,则可能会泄漏连接。如果从 DataContext
检索到的任何实体保持事件状态,您也可能会泄漏内存,因为上下文为其实现的工作单元模式维护内部身份缓存。但是,即使这一切都不是这种情况,您也不关心 Dispose
方法在内部做了什么。假设它做了一些重要的事情。
IDisposable
是一个契约(Contract),上面写着“清理可能不是自动的;你需要在完成后处置我。”如果您忘记 Dispose
,您无法保证该对象是否有自己的终结器在您之后进行清理。实现可能会发生变化,这就是为什么依赖观察到的行为而不是明确的规范不是一个好主意。
如果您使用空的 Dispose
方法处理 IDisposable
可能发生的最糟糕的事情是您浪费了几个 CPU 周期。如果您未能使用非平凡实现处理IDisposable
,可能发生的最糟糕的事情是您泄漏了资源。这里的选择是显而易见的;如果您看到 IDisposable
,请不要忘记处理它。
关于c# - 为什么可以在 DataContext 上调用 Dispose() 后枚举 DbLinq 查询?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2851755/