关于数据库connection与reader相互绑定的疑问

chichenzhe 2012-10-12 03:26:05
    public SqliteDataReader ExecuteQuery(string sqlQuery)
{
try
{
this.connection.Open();
dbCommand = this.connection.CreateCommand();
dbCommand.CommandText = sqlQuery;
DataReader reader = dbCommand.ExecuteReader();
return reader;
}
catch (System.Exception ex)
{
Debug.Log(ex.ToString());
}
finally
{
this.connection.Close();
}
return null;
}



代码就是这样的. 但是不是ms平台的东西 , 所以部分关键字别较真.

我的意思是: 为什么DataReader reader = dbCommand.ExecuteReader(); 所获取到的 reader 必须是和 connection 绑定的呢? 因为当我 finally 把connection关闭的时候 这个方法返回的reader也不可用了.

但从数据的理论上理解, 我的reader凭什么跟你 sql的connection绑定起来? 有何绑定的必要呢?

从逻辑学角度. 无非就是利用 connection 获得了一个open的连接, 然后通过sql脚本把 数据抓到 connction 对象所控制的内存区域里, 然后 connction 再把这些数据吐出来, 吐给要返回的 reader 上. 然后规定 reader 和 connection没有绑定关系即可.

但是实际上. 不管是之前我在java中遇到的. 还是在c#中遇到的, 所有系统库都倾向于去提供一个 connection 与reader 绑定的访问方法. 这肯定有他的道理的. 但道理是什么呢? 我暂时没想明白. 因为我以为: 提供一个 connection与reader互相没有关系的方法是更有用的.
...全文
180 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
zhanglong19891129 2012-10-12
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 的回复:]

引用 5 楼 的回复:

一本书你不打开你能读么?


我说朋友, 你不能这么说啊, 你得动动你的脑筋去想问题,而不是被 类库 所局限死. 就算被局限了, 你也得去理解,别人为什么要这么局限对吧.

我给你举个简单例子:
如果我获得reader之后, 直接在 connection.close之前 把所有 reader 内的数据预读出来, 放进一个 string里,用 *分割. ……
[/Quote]
这个就是你把数据的记住了....如果没有记住数据的时候,你close()就不行了..
lshfong 2012-10-12
  • 打赏
  • 举报
回复
你在关闭连接前先把数据转存出来
chichenzhe 2012-10-12
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 的回复:]

引用 12 楼 的回复:

最最最根本的问题是:

connection 的 reader 实现就是个错的. (有待被其他高手指出我这句话的错误)

connection 不应该提供 一个与之 绑定的 reader.
而应该提供一个 与之完全无绑定关系的 reader. 当connection读取数据之后自动new一个 reader, 然后把这个reader 的数据填充一些, ……
[/Quote]

谢谢,我明白为什么ms这么做了. 相当于把 connection 的 socket read方法直接 抛给业务逻辑层在使用.
基本明白了.

我还是用SqlDataAdapter吧.
sofant 2012-10-12
  • 打赏
  • 举报
回复
如果reader与connection不绑定,reader仍然能够读取数据,那么前提就是数据在本地,不在远程,不需要通去connection这个通道去取。
但是reader的工作方式却是在你需要数据的时候,通过connection去取。
Hauk 2012-10-12
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 的回复:]

最最最根本的问题是:

connection 的 reader 实现就是个错的. (有待被其他高手指出我这句话的错误)

connection 不应该提供 一个与之 绑定的 reader.
而应该提供一个 与之完全无绑定关系的 reader. 当connection读取数据之后自动new一个 reader, 然后把这个reader 的数据填充一些, 然后 把这个 reader 提供给……
[/Quote]

我前面就回答了,比如你查询一个10G的东西,你一对象能装下么?
就算平时没这么大,一次读出来放内存里面那也是开销啊。
chichenzhe 2012-10-12
  • 打赏
  • 举报
回复
最最最根本的问题是:

connection 的 reader 实现就是个错的. (有待被其他高手指出我这句话的错误)

connection 不应该提供 一个与之 绑定的 reader.
而应该提供一个 与之完全无绑定关系的 reader. 当connection读取数据之后自动new一个 reader, 然后把这个reader 的数据填充一些, 然后 把这个 reader 提供给业务层使用.

就是这样. 我认为 ms 和 java 所提供的 connection 的方式错了. 应该按我的需求来.

如果有高手所 ms和sun 是对的, 那么请指出理由 以及 他们的应用场合
Hauk 2012-10-12
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 的回复:]

引用 5 楼 的回复:

一本书你不打开你能读么?


我说朋友, 你不能这么说啊, 你得动动你的脑筋去想问题,而不是被 类库 所局限死. 就算被局限了, 你也得去理解,别人为什么要这么局限对吧.

我给你举个简单例子:
如果我获得reader之后, 直接在 connection.close之前 把所有 reader 内的数据预读出来, 放进一个 string里,用 *分割. ……
[/Quote]


SqlDataAdapter就是一次性把数据全读出来,和connection无关。
SqlDataReader只是另外一种解决方案而已。
你说MS为什么会搞个SqlDataReader这样和connection绑一起的东西呢?
那是因为SqlDataReader是一行一行的去数据库拿东西。
你又问为什么要这样呢?
那是为了解决大数据量的问题。
DataReader 提供未缓冲的数据流,该数据流使过程逻辑可以有效地按顺序处理从数据源中返回的结果。由于数据不在内存中缓存,所以在检索大量数据时,DataReader 是一种适合的选择。
sofant 2012-10-12
  • 打赏
  • 举报
回复
using(var sqlcn = new sqlconnection(...))
using(var sqlcmd = sqlcn.createcommand())
{
sqlcmd.commandtext="....";
using(var sqlreader = sqlcmd.executereader())
{
while(sqlreader.read())
{
//一点一点读,在读的时候,connection这条路当然不能断了
}
}
}

var dt = new datatable();
using(var sqlcn = new sqlconnection(...))
using(var sqladapter=new sqldataadapter("...",sqlcn))
{
sqladapter.fill(dt);//数据一次性填充
}

//这里connection断开了,但是数据全在datatable里,要数据可以在datatable里拿
chichenzhe 2012-10-12
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 的回复:]

DataReader reader = dbCommand.ExecuteReader();
这里相当于c的传了个指针也就是传的对象句柄,C#要想有独立的对象还是需要重新new一个的否则对象之间直接的等于就是传个引用
[/Quote]

new一个然后 深度clone吗?
倒, 我一个简单需求不能说 不给我提供一个简单解决方案吧?

我就是为了返回一个 data. 然后让业务层逻辑不关心 connection 的释放问题 等等.
把这些问题留给 我的 底层方法自己去考虑.
chichenzhe 2012-10-12
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 的回复:]

一本书你不打开你能读么?
[/Quote]

我说朋友, 你不能这么说啊, 你得动动你的脑筋去想问题,而不是被 类库 所局限死. 就算被局限了, 你也得去理解,别人为什么要这么局限对吧.

我给你举个简单例子:
如果我获得reader之后, 直接在 connection.close之前 把所有 reader 内的数据预读出来, 放进一个 string里,用 *分割. 返回这个string给目标地方自行split拆分不就达到我的需求了吗? 这不就是关闭了书本还能继续读书吗.


所以:
你不能说 ms 没给你提供拷贝书本的功能 就认为这是理所当然的啊. 就算是理所当然, 现在. 我在这问的就是: 为什么ms 会这么干? 而不给提供一个 cachedRowSet呢?
zhanglong19891129 2012-10-12
  • 打赏
  • 举报
回复
你看到某个东西,你没有记住的话,你就把书关了,你很定不能用
homejiji 2012-10-12
  • 打赏
  • 举报
回复
DataReader reader = dbCommand.ExecuteReader();
这里相当于c的传了个指针也就是传的对象句柄,C#要想有独立的对象还是需要重新new一个的否则对象之间直接的等于就是传个引用
zhanglong19891129 2012-10-12
  • 打赏
  • 举报
回复
一本书你不打开你能读么?
sofant 2012-10-12
  • 打赏
  • 举报
回复
DataReader并没有把你查的所有数据都放在本地,所以Connection不能销毁。
javax.sql.rowset.CachedRowSet 不懂,根据你的描述应该就是一次性读取数据到本地,.net里可以用DataTable,多张表的话用DataSet,这时connection是可以销毁的。
chichenzhe 2012-10-12
  • 打赏
  • 举报
回复
还有, 为什么 connection 必须 是和 reader 绑定的, 那么多语言都这么设置了.


他们都这么做的理由是什么?
chichenzhe 2012-10-12
  • 打赏
  • 举报
回复
我记得java中为了解决这个问题 我是使用了 javax.sql.rowset.CachedRowSet 的.

CachedRowSet 直接和 PreparedStatement 把关系撇清了.

c#是怎么解决这个问题? 返回 datatable? dataset?
chichenzhe 2012-10-12
  • 打赏
  • 举报
回复
我的需求无非就是我利用 sql的connection获得了数据. 然后我觉得sql的connection对我已经无意义了, 所以我就给他 咔嚓了. 然后我把对我有意义的 数据部分给return到我需要的地方使用.

但问题是, 在我咔嚓connection的时候, 我想使用的 data 也随着这个咔嚓而一起咔嚓了.

这显然不科学, 也不符合正常人思维的,和使用的习惯.

110,549

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧