首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么可以在调用DbLinq ()之后枚举DataContext查询?

为什么可以在调用DbLinq ()之后枚举DataContext查询?
EN

Stack Overflow用户
提问于 2010-05-17 18:38:27
回答 3查看 667关注 0票数 8

更新--答案显然是DbLinq没有正确地实现Dispose()。哦哦!

以下是一些误导的底线:当我最初提出这个问题时,DbLinq还没有(还)等同于LinqToSql。小心使用!

我正在与DbLinq一起使用存储库模式。我的存储库对象实现了IDisposable,而Dispose()方法只在DataContext上调用Dispose()。每当我使用存储库时,我都会将它封装在一个using块中,如下所示:

代码语言:javascript
复制
public IEnumerable<Person> SelectPersons()
{
    using (var repository = _repositorySource.GetPersonRepository())
    {
        return repository.GetAll(); // returns DataContext.Person as an IQueryable<Person>
    }
}

此方法返回一个IEnumerable<Person>,因此如果我的理解是正确的,那么在遍历Enumerable<Person>之前不会实际对数据库进行查询(例如,将其转换为列表或数组,或者在foreach循环中使用它),如本例所示:

代码语言:javascript
复制
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> )之后立即被调用,这是它唯一一次被调用。

因此,有三个问题:

  1. 这是怎么工作的?在disposed?
  2. What已经是Dispose()之后,已被释放的DataContext如何仍然可以查询数据库的结果呢?
  3. --我听说没有必要(例如,参见this question)来处理DataContext,但我的印象是,这不是一个好主意。有什么理由不处理一个DataContext

DbLinq吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2010-05-17 19:58:08

1这是如何工作的?在释放DataContext之后,已释放的DataContext如何仍然查询数据库的结果?

不工作。有些东西你没给我们看。我猜想您的存储库类没有在正确的时间正确地释放DataContext,或者在每个查询结束时草草地编写ToList(),这完全否定了通常得到的查询转换和延迟执行。

在测试应用程序中尝试下面的代码,我保证它会抛出一个ObjectDisposedException

代码语言:javascript
复制
// 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,不要忘记释放它。

票数 3
EN

Stack Overflow用户

发布于 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

票数 0
EN

Stack Overflow用户

发布于 2010-05-17 19:01:00

在API的深处,您可能会看到一个使用像下面这样的api的方法:

http://msdn.microsoft.com/en-us/library/y6wy5a0f(v=VS.100).aspx

执行命令时,关联的连接对象将在关联的DataReader对象关闭时关闭。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2851755

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档