• 转:DataReader 链接关闭解惑篇


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

    不管是啥xxDataReader,都是继承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();
            }

    结论是:

    False
    Open

     

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

     

    情况二: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());
            }

    结果是:

    True

    Closed

     

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

    三:分析原因

     

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

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

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

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

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

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

    public override IEnumerator GetEnumerator()
    {
        
    return new DbEnumerator(this, (this._commandBehavior & CommandBehavior.CloseConnection) == CommandBehavior.CloseConnection);
    }

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

        public DbEnumerator(IDataReader reader, bool closeReader)
        {
            
    if (reader == null)
            {
                
    throw ADP.ArgumentNull("reader");
            }
            
    this._reader = reader;
            
    this.closeReader = closeReader;//此行设置了标志
        }

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

        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;
        }

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

     

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

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

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

     

    四:最终结论是什么?

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

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

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

     

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

    版权声明:本文原创发表于 博客园,作者为 路过秋天,博客 http://cyq1162.cnblogs.com/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则视为侵权。
  • 相关阅读:
    EF系列——DbContext 和DbSet
    EF中的实体关系
    EF中的持久化场景
    Sass
    js里==和===的区别 、sass与less的区别 、style,与class区别(精解版)
    HTML页面加载和解析流程 link与script标签
    DesktopNaotu 百度桌面脑图使用事项
    BootStrap4中使用图标
    Bootstrap4
    CDN文件
  • 原文地址:https://www.cnblogs.com/superfeeling/p/2214091.html
Copyright © 2020-2023  润新知