c# - 通过值与引用构造数据读取器时处理数据读取器

标签 c# reference dispose datareader

关于数据读取器在使用 ref 与 var 在类中构造时实际何时释放的菜鸟问题。我今天一直在测试这个,结果让我有点困惑——希望我能弄清楚这一点。

我有一个类可用于通过 ODBC 从众多远程服务器获取数据,但我需要限制为我所连接的每个服务器打开的 ODBC 连接数——因此我在正确处理数据读取器时要小心当我用完它们后再打开另一个。简短版本是我有一个名为 FillDataReader 的方法,它接受一个数据读取器对象,并根据您的查询填充它并将其传回。

如果我使用 ref 传递它并从调用方处理数据读取器,一切都很好。连接立即释放,客户端可以在不断开连接的情况下获取另一个数据读取器。但是,如果我按值传递,资源不会被释放,如果我从客户端打开另一个数据读取器,我现在有两个到该服务器的连接。

从概念上讲,我明白了区别——使用 ref 时,只有一个地址被使用,因为它正在传递一个“指向指针的指针”,而 dispose 释放该资源。好的,但即使按值传递并在客户端进行显式处理,究竟是什么持有资源?我宁愿在这里按值传递,这样我就可以在客户端使用漂亮的 using 结构,但更重要的是我想更好地理解这里发生的事情。简而言之,这就是它的样子

[数据库获取类]

public bool FillDataReader(string pQueryString, ref System.Data.Odbc.OdbcDataReader pDataReader, out string pErrorReason)
        {
(uses a connection object that’s been established at class construction time and stays up all the time)
...
            try
            {
                pDataReader = _Command.ExecuteReader();
            }
...
         }

[Calling class]

strSQL = "SELECT Alias, ObjectID, FROM vw_GlobalUser";
               if (ServerList[currentServer].DatabaseFunctions.FillDataReader(strSQL, ref drTemp, false, out strErrorReason) == false)
               ….

    drTemp.Dispose();

(at this point the connection is released to the server)

但是,如果我在调用类中的 Dispose 点取出 ref,则不会释放连接。它最终会消失,但我需要它立即消失(因此调用处置)。

那么 DB fetch 类中的 fill 函数是否以某种方式卡在对堆上已分配空间的引用上?我不确定我是否理解为什么会这样——理解它正在使用堆栈上数据读取器的地址的另一个副本来引用那里堆上的数据读取器对象,但是当它超出范围时,它不会被释放吗?也许我需要更多咖啡……

最佳答案

由于您的调用代码需要接收引用以释放对象,因此您确实需要一个ref(或out)。否则参数只传递给方法,而不是返回,因此 drTemp 不会用 FillDataReader 方法中创建的数据读取器更新。

请注意,您可能希望按如下方式更改签名以使意图更清楚:

public Result TryGetDataReader(string pQueryString, out System.Data.Odbc.OdbcDataReader pDataReader)

我建议的更改:

  • 引入了“Try”的命名约定,这对于此类方法是通用的
  • 使 pDataReader 成为out,因为调用方法时不需要初始化
  • 引入了一个“Result”类型,它应该携带成功信息和错误信息(如果有的话)

关于c# - 通过值与引用构造数据读取器时处理数据读取器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6557792/

相关文章:

c# - 是否有可能知道 wpf 中的样式中有哪些 setter 可用?

c# - 使用 c#/ASP.NET 以编程方式伪造网站登录

c# - WinForm 组合框上的空错误

c++ - 为什么引用大小总是 4 个字节 - c++

android - 如何在android中添加对项目的引用?

c# - 如何使用 Entity Framework 将现有实体添加为新实体

java - 重新分配引用对象时对内存的影响

java - libGDX 我应该在哪里使用 dispose/如何使对象成为一次性对象?

Java CountDownLatch 用于等待 JFrame 处理

c# - 何时处置以及为什么?