今天跟大家伙儿唠唠我最近折腾的 `OleDbDataReader`。一开始接触这玩意儿,我是有点懵的,感觉就是个黑盒子,往里头塞东西,然后出来一堆看不懂的数据。不过经过一番摸索和实践,总算是搞明白,现在就来分享一下我的心得。
我接到一个任务,需要从一个老旧的 Access 数据库里读取数据。这数据库老得掉牙,只能用 `OleDb` 来连接。当时我就想,完犊子,这玩意儿我没怎么用过。没办法,硬着头皮上呗。
肯定是创建数据库连接,这个没啥难度,网上搜一下,一大堆代码,直接抄过来,改改连接字符串就行。关键是后面的数据读取,用的是 OleDbCommand
对象,我执行查询,然后想着怎么把数据弄出来。
然后,我发现 `OleDbDataReader` 这玩意儿。一开始我以为它是个数组,直接用索引去取数据,结果发现根本不行。后来才知道,它是一个只进的读取器,得一行一行地读。就像一条传送带,你只能从头开始,一个一个地拿,不能跳着拿,也不能往回拿。
于是我就开始写代码,先创建一个 OleDbDataReader
对象,然后用一个 `while` 循环,不断地调用 `Read()` 方法。这 `Read()` 方法就像是传送带的开关,每调用一次,它就向前移动一格,指向下一行数据。如果已经到末尾,它就返回 `false`,循环就结束。
在循环里面,我用 `GetString()`、`GetInt32()` 等方法来获取每一列的数据。这些方法都需要指定列的索引,也就是第几列。一开始我搞错,以为索引是从 1 开始的,结果总是报错。后来才知道,索引是从 0 开始的,跟数组一样。真是一不小心就掉坑里。
举个例子:
假如我有个 SQL 查询语句是 SELECT ID, Name, Age FROM Users
,那么:
*32(0)
获取的就是 `ID` 列的值*(1)
获取的就是 `Name` 列的值*32(2)
获取的就是 `Age` 列的值
但是,这里有个坑,就是类型转换。如果数据库里的类型跟 `GetString()`、`GetInt32()` 这些方法不匹配,就会报错。比如,如果 `Age` 列在数据库里是字符串类型,你用 `GetInt32()` 去取,就会报错。一定要注意类型匹配,或者用 `*32()` 之类的函数进行转换。
我还遇到一个问题,就是有的字段是 `null` 值。如果直接用 `GetString()`、`GetInt32()` 去取 `null` 值,也会报错。在取值之前,要先用 `IsDBNull()` 方法判断一下是否为 `null`。如果是 `null`,就给它赋一个默认值,比如空字符串或者 0。
代码大概是这样:
if (!*(1)) { string name = *(1); } else { string name = ""; }
还有一个需要注意的地方,就是 `OleDbDataReader` 必须独占一个数据库连接。也就是说,在读取数据的过程中,不能用同一个连接去执行其他的 SQL 语句。否则,就会报错。最好在读取完数据之后,立即关闭连接。
我还发现,用 `OleDbDataReader` 读取大量数据的时候,速度还是挺快的。因为它是一个只进的流,不需要把所有的数据都加载到内存里,可以逐行读取,节省内存空间。
`OleDbDataReader` 虽然用起来有点麻烦,但是功能还是很强大的。只要掌握它的基本用法,注意一些细节问题,就可以轻松地从 Access 数据库里读取数据。
总结一下
这回折腾 `OleDbDataReader`,我主要做这么几件事:
- 连接 Access 数据库
- 创建
OleDbCommand
对象,执行 SQL 查询 - 创建
OleDbDataReader
对象,读取查询结果 - 使用
Read()
方法逐行读取数据 - 使用
GetString()
、GetInt32()
等方法获取单元格值 - 处理
null
值和类型转换问题 - 关闭数据库连接
希望我的分享对大家有所帮助!