以下是所有类型的误导 – 底线:DbLinq(尚未)等同于LinqTosql,正如我最初提出这个问题时所假设的那样.请谨慎使用!
我正在使用DbLinq的Repository Pattern.我的存储库对象实现了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
在这个例子中,在设置person之后立即调用Dispose(),这是一个IEnumerable< Person>,这是它被调用的唯一时间.
那么,有三个问题:
>这是如何工作的?在处理DataContext之后,处理后的DataContext如何仍然在数据库中查询结果?
> Dispose()实际上做了什么?
>我听说没有必要(例如,见this question)处理DataContext,但我的印象是这不是一个坏主意.有没有理由不处理DbLinq DataContext?
解决方法
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(),那么查询结果已经在使用块中枚举,我敢打赌在您的情况下发生了什么.
2 What does Dispose() actually do?
除此之外,它还设置了一个标志,表明DataContext已被处理,并在每个后续查询中进行检查,并使DataContext抛出一个ObjectDisposedException,其消息为Object name:’Dispose后访问DataContext’.
如果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是一份合同,上面写着“清理可能不是自动的;你需要在完成后处理我.”如果您忘记Dispose,则无法保证对象是否有自己的终结器可以清理.实现可能会发生变化,这就是为什么依赖观察到的行为而不是明确的规范并不是一个好主意.
如果使用空Dispose方法处理IDisposable,最糟糕的事情就是浪费了几个cpu周期.如果您未能通过非平凡的实现来处置IDisposable,那么最糟糕的事情就是泄漏资源.这里的选择很明显;如果你看到IDisposable,不要忘记处理它.