zoukankan      html  css  js  c++  java
  • sqlcommand对象 datareader对象

    sqlcommand主要是通过sqlconnection来发命令的。

    最常用的是发 select命令,这就要先来说说sqldatareader 的工作机制了:

    datareader的实现机制是游标,游标的类型有三种:1 静态游标2 键值游标3动态游标

    三种游标区别如下:

     静态游标:每当发一条select命令的时候,静态游标会在临时数据库中生成临时表, 把选中的数据全都加载到这个临时表,然后用一个指针来指向这个临时表,这个时候不会产生不可重复读和幻想的问题。

    键值游标: 每当发一条select命令的时候,键值游标也会生成一个临时表,但是它加载 到临时表中的数据只有键,怎样理解这个键,用过dictionary<key,value>吧,通过这个来理解就很容易了,就是说到

                   这个临时表的数    据不 是选中的所有字段,而是键进去了,这个时候不会产生幻想问题,但是会出现不可重复读的问题。

    动态游标: 动态游标为了效率问题,不会产生任何临时表,它直接在原有数据库的基础上来流水前进,只进不退,这也是为了效率才这个设计的,

                   在读数据的时候会加S锁,读完这条数据就解S锁,然后去读下一条。因此效率很高。

    好了,来说说sqldatareader把,SQL 中的游标是第三种,即动态游标,在RC隔离级别下,它在数据的时候,读取一条数据时候会把数据加S锁

     同时加U锁,读后就把S和U锁都撤销,然后去读下一条数据,内存模型如下:

    它在执行的时候会把数据库的表的元数据读取到,即把表的架构先拿到,有哪些列,哪些类型等等,然后才去读数据,

    图中”数据“部分其实是个缓冲区,一次读了多条,而不是缓冲区只能放一条数据,这样还是为了效率问题,减少和DISK

    的交互次数,效率自然好点,想想,如果它使用完后不释放,会出现什么情况?前台和后台都会有资源浪费,因为服务器端

    的read 要保留这个对象,等待再读,而前台也浪费了资源。一个连接在默认情况下是只能有一个游标的,如果这个游标一直

    不关闭,则就不能执行其他的想要通过游标来完成的命令。要想可用多个游标,请启用MARS.

             datareader能完成两块任务,1 读取元数据,2 获取数据。

    通过元数据可以获取的数据的很多,有点要注意,把数据库中的列名读取到datareader的元数据的时候,如果用到了别名,

    那么在元数据中加载的是别名,而得不到数据库中原始的列名包括列名,列个数,每个的类型(.NET或者SqlType)以及字

    段的序号。

    注意读取数据列的时候有个效率问题,是基于列名来读取还是基于列序号来读,如果你用的是基于列名来读的,内部要转换成

    列序号来实现用列序号来读取比列名来读取要快6%左右,可以看到,通过列名来读取大量数据效率是很低的,可以通过列命

    转换为序号,然后以后读取数据都通过这个序号来读取。

    读取的时候NULL 的处理,如果数据库中的类型是引用类型,这没什么,如果是值类型的话,数据库的值类型是可空的,但是.NET

    中的值类型是不能为NULL的,因此一旦数据库中某个字段是可空类型的,在把它赋值给.NET类型的时候是一定要进行处理的。

    另外注意到,如果知道了某列的数据类型,你可以使用强类型来直接读取,这样就省去了类型转换的时间

       read刚开始读取数据的时候是指向表的开头,不指向任何的有效数据,当fetch一次的时候,指针向下移动指向一条有效的数据。

       如果数据读完了,就返回false。在读取数据的时候有俩个问题一定要处理 1,NULL  2 .NET 与 SQL的数据兼容类型。s

      1 executereader()  内部的实现机制就是上面说到的动态游标。在读取数据的时候,如果用了别名,则datareader 的数据区用的是

                                 别名,这样维护性就更好点,不因数据库的字段命改变而改变

      2 executescalar(  )的内部执行机制也是动态游标,但是自动调用了(someType)read[0];

      2 executeNonQuery()将返回受影响的行数,如果是执行非数据库操作语言的话,返回-1

       事务中执行命令:

       sqlconnection一旦开了一个事务,则执行的命令就必须和事务相关。

      如果在using代码中的尾部没有提交或回滚事务,则会隐式的调用rollback()方法来回滚。

    非事务的命令:

    如有以下命令(没有开启事务去执行)

    select ***

    update***

    insert***

    GO

    如果几条语句没有语法错误,在执行的时候发生了运行时错误,那会怎样处理呢,比如update发生了错误,那么select和insert都

    还是要去执行的,而不是中断回滚,这就是非事务的危险之一。

    1 如果语法有错,则所有语句都不执行。

    2如果运行时有错,则跳过这个错误,继续执行下面的语句。

    故尽可能的使用事务来提交命令。

    总的来看sqlcommand对象是和数据库中的数据交互的,可以基于异步和同步,就同步来说,提取数据的时候要用到datareader

    ,它的细节应该再次 注意,工作原理,元数据和数据,推进方式,加锁方式,读取数据时候用列名还是序号,使用强类型更快,注

    意数据类型的兼容和NULL值处理,在向数据库发数据时候注意,事务和非事务的特点,参数化执行等等

    
  • 相关阅读:
    【转】深入理解CSS定位中的偏移
    【转】css清除浮动float的三种方法总结,为什么清浮动?浮动会有那些影响?
    执行sql时出现错误 extraneous input ';' expecting EOF near '<EOF>'
    jquery操作select(增加,删除,清空)
    mybatis 错误CGLIB is not available
    spring事务不会进行回滚的情况
    Hive 存储类型 StoreType
    Sublimetext3安装Emmet插件步骤
    spring-mvc List及数组的配置接收
    solr 学习片段
  • 原文地址:https://www.cnblogs.com/qianyz/p/1848079.html
Copyright © 2011-2022 走看看