天天看点

DataReader 链接关闭解惑篇

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

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

示例代码:

DataReader 链接关闭解惑篇

static void main(string[] args)

        {

            sqlconnection con = new sqlconnection("server=.;database=myspace;uid=sa;pwd=123456");

            con.open();

            sqlcommand com = new sqlcommand("select top 1 id from blog_user",con);

            sqldatareader sdr = com.executereader(system.data.commandbehavior.closeconnection);

            while (sdr.read())

            {

            }

            console.writeline(sdr.isclosed);

            console.writeline(con.state.tostring());

            console.readline();

        }

DataReader 链接关闭解惑篇

结论是:

false

open

说明:默认无论是不是加system.data.commandbehavior.closeconnection,读取时数据库链接不会帮你关闭。

情况二:datareader 链接已关闭

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

DataReader 链接关闭解惑篇

        protected void bind()

            sqlconnection conn = new sqlconnection(configurationmanager.connectionstrings["constr"].tostring());

            conn.open();

            sqlcommand cmd = new sqlcommand("getalluser", conn);

            sqldatareader sdr = cmd.executereader(commandbehavior.closeconnection);

            repeater1.datasource = sdr;

            repeater1.databind();

            response.write(sdr.isclosed.tostring() + "<br/>");

            response.write(conn.state.tostring());

DataReader 链接关闭解惑篇

结果是:

true

closed

情况:system.data.commandbehavior.closeconnection加完之后,链接给你关闭了,为啥?看下面的分析原因。

三:分析原因

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

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

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

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

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

public override ienumerator getenumerator()

{

    return new dbenumerator(this, (this._commandbehavior & commandbehavior.closeconnection) == commandbehavior.closeconnection);

}

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

DataReader 链接关闭解惑篇

    public dbenumerator(idatareader reader, bool closereader)

    {

        if (reader == null)

            throw adp.argumentnull("reader");

        this._reader = reader;

        this.closereader = closereader;//此行设置了标志

    }

DataReader 链接关闭解惑篇

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

DataReader 链接关闭解惑篇

    public bool movenext()

        if (this._schemainfo == null)

            this.buildschemainfo();

        this._current = null;

        if (this._reader.read())//此方法被调用一次,就读一次

            object[] values = new object[this._schemainfo.length];

            this._reader.getvalues(values);

            this._current = new datarecordinternal(this._schemainfo, values, this._descriptors, this._fieldnamelookup);

            return true;//有数据时直接返回,不会执行下面的关闭链接

        if (this.closereader)//好,能进行这里,说明上面读不到数据,简说就是数据读完了

            this._reader.close();//关闭链接操作。

        return false;

DataReader 链接关闭解惑篇

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

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

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

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

四:最终结论是什么?

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

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

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

好了,打完收工,希望对大伙有所帮助。