为什么是它可以列举一DbLinq查询后,调Dispose()上属性?
题
更新 -答案是显然这DbLinq没有实现 Dispose()
正确。D'oh!
以下是所有的排序有误导性-的底线:DbLinq是没有(尚未)相当于LinqToSql,我假定当我最初来问这个问题。使用它以小心!
我使用的储存库模式与DbLinq.我的储存库的目的实施 IDisposable
, , Dispose()
方法不会只有一件事--电话 Dispose()
在 DataContext
.只要我使用一个仓库我把它包装在一个 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>
, 这就是只有时它被称为。
因此,三个问题:
- 这怎么工作的?怎么可能一个布置
DataContext
仍在数据库中查询后的结果DataContext
已经布置的? - 这是什么
Dispose()
实际上做什么? - 我听说这是没有必要(例如,请参阅 这个问题)处置
DataContext
, 但我的印象是,它不是一个糟糕的想法。没有任何理由 不 要处理的一个DbLinqDataContext
?
解决方案
1这怎么工作的?如何可以设置一个属性仍在数据库中查询结果后的属性已被置?
它的 不不 的工作。有些东西你们不是表示我们。我猜你的存储库类不处理的 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这是什么Dispose()实际上做什么?
除其他事项外,它将设置一个标志,指示 DataContext
布置的,这是检查每一个后续查询和原因的 DataContext
扔一个 ObjectDisposedException
有消息 Object name: 'DataContext accessed after Dispose.'.
它还关闭连接,如果 DataContext
打开它,并把它打开。
3我听说这是没有必要(例如,见这一问题),以处理的一个属性,但我的印象是,它不是一个糟糕的想法。没有任何理由不处理的一个LinqToSql属性?
它的 是 有必要 Dispose
的 DataContext
, ,因为它是必要的 Dispose
每一个其他的 IDisposable
.你可能会泄露的连接,如果你不处理掉的 DataContext
.你也可以泄漏的记忆,如果任何实体从 DataContext
被保持存活,由于该背景下维护一个内部的身份缓存单元的工作模式,它实现了。但是,即使没有这样的情况下, 这不是你的关心 什么样的 Dispose
方法并在内部。假设它确实一些重要的东西。
IDisposable
是一个 合同 说,"清理可能不是自动的;你需要处理我,当你完成。" 你有没有保障,是否对象都有其自身的终结,清除后如果你忘记 Dispose
.实现受到改变,这就是为什么它不是一个好主意,依靠观察到的行为而不是明确的规格。
最糟糕的事情可以发生,如果你处理一个 IDisposable
有一个空的 Dispose
方法是,你浪费了几CPU周期。最糟糕的事情可以发生,如果你 失败 处理一个 IDisposable
与 非平凡的执行情况 这是你泄露的资源。选择这里是显而易见的;如果你看到一个 IDisposable
, ,不要忘记处理它。
其他提示
"人"是一个综合的收集、属性(仓库)只是需要做的.GetNew的呼吁。
从选择/等关键词的语法糖扩展的方法加入该系统。皇宫的名字空间。这些扩展的方法增加的综合功能使用的查询,不属性.事实上,你可以做所有这一切都没有使用LINQ2SQL在,通过编程方式创造一种类型证明。
如果你试图作出任何进一步的储存库(属性)电话使用这些目的,这时候,你将会收到一个错误。
该类型的收集将包含所有的记录,从你的储存库,这就是为什么你不需要属性做出的查询。
扩展方法: http://msdn.microsoft.com/en-us/library/bb383977.aspx
皇宫的扩展方法:http://msdn.microsoft.com/en-us/library/system.linq.enumerable_members.aspx
内心深处,你可能会看到一个方法中使用这样一:
http://msdn.microsoft.com/en-us/library/y6wy5a0f(v=VS。100).aspx
在执行命令时,相关的连接目的是关闭时的相关数据读取器目的是关闭的。