king

DataReader链接关闭解惑篇

king 运维技术 2022-11-19 589浏览 0

看到有帖子:DataReader的关闭问题疑惑篇 ,大伙对链接关闭问题看似比较迷惑,这里就给解说一下:

不管是啥xxDataReader,都是继承DataReader实现的,所以是有共性的,因此标题就以DataReader为题了。

情况一:DataReader 默认链接不关闭

示例代码:

staticvoidMain(string[]args) 
{ 
SqlConnectioncon=newSqlConnection("server=.;database=MySpace;uid=sa;pwd=123456"); 
con.Open(); 
SqlCommandcom=newSqlCommand("selecttop1idfromblog_user",con); 
SqlDataReadersdr=com.ExecuteReader(System.Data.CommandBehavior.CloseConnection); 
while(sdr.Read()) 
{ 
} 
Console.WriteLine(sdr.IsClosed); 
Console.WriteLine(con.State.ToString()); 
Console.ReadLine(); 
}

结论是:

False

Open

说明:默认无论是不是加System.Data.CommandBehavior.CloseConnection,读取时数据库链接不会帮你关闭。

情况二:DataReader 链接已关闭

示例代码:[以下是原文的代码]

protectedvoidbind() 
{ 
SqlConnectionconn=newSqlConnection(ConfigurationManager.ConnectionStrings["constr"].ToString()); 
conn.Open(); 
SqlCommandcmd=newSqlCommand("GetAllUser",conn); 
SqlDataReadersdr=cmd.ExecuteReader(CommandBehavior.CloseConnection); 
repeater1.DataSource=sdr; 
repeater1.DataBind(); 
Response.Write(sdr.IsClosed.ToString()+"<br/>"); 
Response.Write(conn.State.ToString()); 
} 

结果是:

True

Closed

情况:System.Data.CommandBehavior.CloseConnection加完之后,链接给你关闭了,为啥?看下面的分析原因。

三:分析原因

1:从前面的两个示例上看,区别是什么?

答:区别就在于一个只读数据,另一个绑定了数据列表控件。

2:为什么绑定了数据列表控件就会自动关闭链接?

答:这就涉及到数据控件绑定机制了,这里给大伙简单介绍一下:

A:要实现数据控件列表绑定,有一个接口是需要实现的:IEnumerable

B:实现DataReader实现此接口的代码[基类是抽象方法,所以只能到子类SqlDataReader查看]:

publicoverrideIEnumeratorGetEnumerator() 
{ 
returnnewDbEnumerator(this,(this._commandBehavior&CommandBehavior.CloseConnection)==CommandBehavior.CloseConnection); 
} 

从这代码里,我们只看到了它把CloseConnection传进DbEnumerator里了,再进去看一下:

publicDbEnumerator(IDataReaderreader,boolcloseReader) 
{ 
if(reader==null) 
{ 
throwADP.ArgumentNull("reader"); 
} 
this._reader=reader; 
this.closeReader=closeReader;//此行设置了标志 
} 

点进去只看到构造函数,并把它赋给this.closeReader属性,因为DataReader是向前读方式,所以重点还是要看其中的一个方法MoveNext:

publicboolMoveNext() 
{ 
if(this._schemaInfo==null) 
{ 
this.BuildSchemaInfo(); 
} 
this._current=null; 
if(this._reader.Read())//此方法被调用一次,就读一次 
{ 
object[]values=newobject[this._schemaInfo.Length]; 
this._reader.GetValues(values); 
this._current=newDataRecordInternal(this._schemaInfo,values,this._descriptors,this._fieldNameLookup); 
returntrue;//有数据时直接返回,不会执行下面的关闭链接 
} 
if(this.closeReader)//好,能进行这里,说明上面读不到数据,简说就是数据读完了 
{ 
this._reader.Close();//关闭链接操作。 
} 
returnfalse; 
} 

以上代码就看我注释的说明。

C:为什么用DataReader绑定列表控件是耍流氓?

答:因为服务端控件列表渲染出表格的周期通常比较长,所以,只有等到你看到最后结果列表出来的时候,最后一行数据才读完。

因此链接是持续相当长的处于打开状态,所以web这种并发多的情况,狂点几下,估计就报错了,链接池用满了。

四:最终结论是什么?

1:在绑定列表控件时,只要数据行读取完毕,就会自动关闭链接。

2:在直接读取时,不会触发绑定相关的读取,所以不会自动关闭链接。

3:在绑定列表控件时,链接长期得不到关闭,并发一来,就挂了,因此大伙就不要耍流氓了。

继续浏览有关 SQL Server 的文章
发表评论