c# - 为什么可以在 DataContext 上调用 Dispose() 后枚举 DbLinq 查询?

标签 c# dblinq

更新 - 答案显然是 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> ,这是它唯一一次被调用。

那么,三个问题:

  1. 这是如何运作的?如何处置DataContextDataContext 之后仍然在数据库中查询结果已经处置了吗?
  2. 什么是Dispose()真的吗?
  3. 我听说没有必要(例如,参见 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(),则查询结果已经在 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/

相关文章:

c# - 按后退按钮时显示警报

c# - BitBlt 代码不工作

database - DbMetal 对 SQLite 中重复的外键引用感到窒息——有什么想法吗?

sqlite - 使用 DBLinq、SQLite 的代码示例

c# - 更改 MySQL/Dblinq 项目中的语言/文化

c# - 在类型 Nullable<Int32> 和 Int32 之间未定义 Equal

c# - 如何修复 “A reference to ' Audio Precision AP2700 3.00对象库'无法添加”

c# - 如何更改图片框(winform)的边框颜色?

c# - 如何在 Xamarin.forms 中强制详细信息页面与 iPad 上的母版页一起右移

c# - 如何将 LinqToSql Table<TEntity> 转换为 Table<IEntity> where TEntity : IEntity?