更新--答案显然是DbLinq没有正确地实现Dispose()。哦哦!
以下是一些误导的底线:当我最初提出这个问题时,DbLinq还没有(还)等同于LinqToSql。小心使用!
我正在与DbLinq一起使用存储库模式。我的存储库对象实现了IDisposable,而Dispose()方法只在DataContext上调用Dispose()。每当我使用存储库时,我都会将它封装在一个using块中,如下所示:
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> )之后立即被调用,这是它唯一一次被调用。
因此,有三个问题:
Dispose()之后,已被释放的DataContext如何仍然可以查询数据库的结果呢?DataContext,但我的印象是,这不是一个好主意。有什么理由不处理一个DataContextDbLinq吗?
发布于 2010-05-17 19:58:08
1这是如何工作的?在释放DataContext之后,已释放的DataContext如何仍然查询数据库的结果?
它不工作。有些东西你没给我们看。我猜想您的存储库类没有在正确的时间正确地释放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(),那么查询结果已经在using块中进行了枚举,我敢打赌,这就是在您的情况下所发生的事情。
2处分()实际上是做什么的?
除其他外,它还设置了一个标志,指示DataContext已被释放,该标志将在每个后续查询上进行检查,并导致DataContext抛出带有消息Object name: 'DataContext accessed after Dispose.'.的ObjectDisposedException。
如果DataContext打开并保持连接打开,它也会关闭连接。
3我听说没有必要(例如,请看这个问题)来处理DataContext,但我的印象是,这不是一个好主意。是否有任何理由不处理LinqToSql DataContext?
它是 Dispose Dispose DataContext的必要条件,也是Dispose其他IDisposable所必需的。如果未能释放DataContext,则可能会泄漏连接。如果从DataContext检索到的任何实体都保持活动状态,也可能会泄漏内存,因为上下文为其实现的工作单元模式维护内部标识缓存。但是,即使没有这样的情况,Dispose方法在内部所做的事情也不是您所关心的。假设它能做一些重要的事情。
IDisposable是一个合同,它说:“清理可能不是自动的,您需要在完成后处理我。”如果忘记使用Dispose,则无法保证对象是否有自己的终结器。实现是可以更改的,这就是为什么依赖观察到的行为而不是显式规范不是一个好主意。
如果您使用一个空的IDisposable方法处理一个Dispose,那么最糟糕的情况就是浪费几个CPU周期。如果不能使用非平凡的实现来释放IDisposable,那么最糟糕的情况就是泄漏资源。这里的选择是显而易见的;如果您看到一个IDisposable,不要忘记释放它。
发布于 2010-05-17 18:49:48
"persons“是一个IEnumerable集合,只需要DataContext (存储库)进行.GetNew调用。
from/select/etc关键字是添加到System.Linq命名空间中的扩展方法的语法糖。这些扩展方法添加了您在查询中使用的IEnumerable功能,而不是DataContext。实际上,您完全可以通过编程创建一个要演示的LINQ2SQL来完成所有这一切,而无需使用IEnumerable。
如果您试图使用这些对象进行任何进一步的存储库(DataContext)调用,那么就会收到一个错误。
IEnumerable集合将包含存储库中的所有记录,这就是不需要DataContext进行查询的原因。
扩展方法:http://msdn.microsoft.com/en-us/library/bb383977.aspx
LINQ扩展方法:http://msdn.microsoft.com/en-us/library/system.linq.enumerable_members.aspx
发布于 2010-05-17 19:01:00
在API的深处,您可能会看到一个使用像下面这样的api的方法:
http://msdn.microsoft.com/en-us/library/y6wy5a0f(v=VS.100).aspx
执行命令时,关联的连接对象将在关联的DataReader对象关闭时关闭。
https://stackoverflow.com/questions/2851755
复制相似问题