ADO.NET编程之美----数据访问方式(面向连接与面向无连接)

  最近,在学习ADO.NET时,其中提到了数据访问方式:面向连接与面向无连接。于是,百度了一下,发现并没有很好的资料,然而,在学校图书馆中发现一本好书(《ASP.NET MVC5 网站开发之美》,当然,我不是做广告的,只因它确实还可以),里面关于二者之间的区别及原理讲得很清楚,下面我们就进入主题。今天心情不错。。。。

  我们都知道ADO.NET提供了对数据库或外部数据源的数据访问接口,它本身实现了面向连接与面向无连接的数据访问方式。面向连接是以数据库连接为基础的,在打开数据库连接后,将数据访问指令送入数据库内执行后,利用游标来存取结果集的访问模式,优点是访问速度快,缺点则是必须建立连接,且会有锁定问题;面向无连接则是先以面向连接的方式获取数据后,将数据存放在内存里,再通过一系列的对象、属性与方法等进行数据的访问,而这些访问工作都是在内存内进行的,与数据库并没有维持连接,优点是节约数据库的连接资源且没有访问的锁定问题,但缺点就是耗费内存,且数据的更新不会反映到数据库内。

下面来看看具体的原理吧。

  面向连接的操作

     面向连接的操作以IDbConnection接口为起点,通过OPen()打开数据库连接,在操作数据库完成后用Close()关闭连接并且释放资源。若是需要数据库事务处理,则要在连接打开后使用BeginTransaction方法启动事务处理,并得到IDbTransaction接口的对象。事务处理的动作一般来说不是全部完成就是全部失败,因此在执行过程中若发生任何错误或是需要撤销事务处理时可使用Rollback()来撤销,反之则使用Commit()来提示执行完成。ADO.NET也是允许事务处理启动时设置事务处理的隔离层次。

    当连接打开后,即可对数据库进行SQL指令的操作,而在执行SQL指令前,必须先将指令封装于IDbCommand接口对象,这个对象内含了参数的设置,而在SQL指令中使用参数是预防SQL Injecion的最好方法,对象也提供了控制执行方式的配置设置,例如:执行超时(Timeout),指令准时(Prepare)以及加入事务处理等设置。当指令设置完成时,就可以通过ExecuteReader()、ExecuteNonQuery()以及ExecuteScalar()来执行。

    ExecuteReader()会传回IDataReader接口对象,IDataReader接口对象代表了数据库返回的单向前向游标,并且单向前向游标是只读的,所以不能直接操作IDataReader接口对象来修改数据,修改数据唯一可用的方法只有执行INSERT、UPDATE和DELETE这三个SQL指令,这样的方法能让程序访问数据库的速度加快不少,而且ADO.NET也不再需要维护数据集的游标相对的节约耗用的资源ExecuteReader()是获取IDateReader接口对象的唯一方法,而IDbCommand的其他方法,如ExecueNonQuery()以及ExecuteScalar()都调用了ExecuteReader()来执行指令,只是最后返回的值不同而已。

    IDateReader接口对象的使用相当简单,每调用一次Read方法即可将游标往前移动一行(每行都是一个IDateReader接口对象),而在游标移动后,就可以通过GetValue()来获取字段的值,或者通过使用GetOrdinal()获取字段的索引编号,也可以通过使用IsDBNull()来判断字段是否为NULL值等。

  面向无连接的操作

    为了支持面向无连接的对象,ADO.NET提供了IDateAdapter接口以及IDbDataAdapter接口对象以支持脱机数据的填充和更新。IDataAdapter接口内包含了Fill()以及Update()分别掌管数据的填充与更新,而IDbDataAdapter接口对象则包含了SelectCommand、InsertCommand、UpdateCommand与DeleteCommand等4中指令,以支持脱机数据的CRUD等4项工作。

    脱机功能是ADO.NET的特色之一,由DataSet与DataTable提供,DataSet可视为内存里的数据库,DataTable则是内存里的数据表,一个DataSet可以容纳多个DataTable,就像数据库内可以容纳多个数据表一样,并且DataTable之间也可以拥有条件以及关联的设置。

    DataSet的数据有面向无连接的IDbDataAdapter接口对象的Fill()获得的,IDbDataAdapter会利用SelectCommand属性所内含的SELECT指令执行的结果来生成相应的DataTable,并加到DataSet内,或是直接以Fill()生成DataTable,再手动加到DataSet亦可。DataSet本身也支持对XML数据的输入和输出,只要调用ReadXml()即可由XML数据生成DataSet,或调用WriteXml()生成XML数据,DataTable也具有相同的方法。DataSet和DataTable也同时支持合并的功能,DataSet和DataTable的Merge()允许程序将两个数据集或数据行合并,同时视MissingSchemaAction所定义的方法判断如何针对遗失或无法对应的结构字段做处理。

    DataTable是实际储存数据的对象,它本身是一个内含大量集合对象的容器,DataTable内容纳了定义字段的DataColumn对象以及加载数据的 DataRow对象,每个DataRow代表一个数据行,因此数据行端的判断与操作都可以在DataRow的成员中找到,例如判断字段是否为NULL值的IsNull(),传回所有数据的ItemArray属性,以及判断是否有改变的RowState属性等。DataColumn对象则专司字段的数据类型与格式定义,DataRow内的字段基本上一定会和DataTable的Columns属性内容的DataColumn对象相同。

    每个DataRow都有标记版本的概念,DataRow对象内含的RowState属性担当了控制版本的角色。RowState默认的值为Unchanged,当DataRow被加入到DataTable时,RowState会被设置为Added,当程序修改了DataRow内的数据,或是调用DataRow的SetModified()时,会将RowState转换为Modified;当调用DataTable的Remove()删除数据行时,RowState会被设为Deleted。DataTable的Getchanged会搜索所有RowState不是Unchanged的DataRow对象,并传回一个DataTable ,以利于程序找出所有被修改过的数据行,AcceptChanges()会将所有修改过的数据行的RowState全部转换为Unchanged,并将删除的数据行从DataTable中删除,而RejectChanges()则会将修改过的数据行恢复到原来的状态,把修改过或删除的值复原,并将新增的数据行从DataTable中删除。IDbDataAdapter的Update()利用数据行的版本来决定调用INsertCommand、UodateCommand或DeleteCommand。

    除了基本的数据管理外,DataTable也支持数据的搜索与汇总功能,Select()允许程序使用搜索指令来检索数据行,并传回符合的数据集,Compute()则允许程序使用汇总指令对数据行进行汇总处理,例如SUM或是AVG等指令。DataTable内也可以设置与其他DataTable的关联,关联对象由DataRelation对象提供,不过,DataRelation对象只记录DataTable之间的关联,而不实际负责数据的控制。与DataRelaion对象相似的是Constraint对象,它允许程序对数据列内的数据进行限制,例如外键限制或是唯一性限制等,这些限制会在数据行操作时自动由DataTable进行检查。脱机数据也可支持特定范围的数据处理功能,此功能由DataView提供,DataView对象内的RowFilter属性可设置DataView如何过滤DataTable内的数据行,或是运用RowStateFilter属性针对RowState进行过滤。DataView也提供创建与修改的功能,或是将过滤出的数据列汇集成新的DataTable。

时间: 2024-11-08 18:23:22

ADO.NET编程之美----数据访问方式(面向连接与面向无连接)的相关文章

[翻译]比较ADO.NET中的不同数据访问技术(Performance Comparison:Data Access Techniques)

Performance Comparison: Data Access Techniques Priya DhawanMicrosoft Developer Network January 2002 原文链接:https://msdn.microsoft.com/en-us/library/ms978388.aspx 概要:在典型的应用环境中,比较不同数据访问技术的表现性能.适用于Microsoft .NET Framework Beta2 和 Microsoft SQL Server 2000

ADO.NET笔记——使用通用数据访问

相关知识: 前面所有示例,君是访问特定的数据库(SQL Server),因此注入SqlConnection.SqlCommand.SqlDataReader.SqlDataAdapter等类名都添加了“Sql”的前缀,并且隶属于System.Data.SqlClient命名空间.这就给代码的可移植性带来了巨大问题.如果数据库改用Oracle.MySQL或者BD2,代码几乎要全部重写,非常不利于重用. System.Data.Common命名空间提供了一组类和操作,使得程序可以忽略底层数据库的差异

ado.net 实体类_数据访问类

实体类: using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace 实体类_数据访问类.App_Code { public class Users { private int _code; /// <summary> /// code /// </summary> public int Code { get { return _code; } set

ADO,NET 实体类 和 数据访问类

啥也不说,看代码. --SQl中 --建立ren的数据库,插入一条信息 create database ren go use ren go create table xinxi ( code nvarchar(20) primary key,--编号 name nvarchar(20)--名字 ) insert into xinxi values('1001','zhangsan') 1.建立实体类: 实体类:封装封装一个类,类名与数据库表名一致成员变量名与列名一致,多一个下划线成员变量封装完的

007-elasticsearch【一】概述、Elasticsearch 访问方式、Elasticsearch 面向文档、常用概念

一.概述 Elasticsearch 是一个开源的搜索引擎,建立在一个全文搜索引擎库 Apache Lucene™ 基础之上. Elasticsearch 也是使用 Java 编写的,它的内部使用 Lucene 做索引与搜索,但是它的目标是使全文检索变得简单, 通过隐藏 Lucene 的复杂性,取而代之的提供一套简单一致的 RESTful API. 然而,Elasticsearch 不仅仅是 Lucene,并且也不仅仅只是一个全文搜索引擎. 它可以被下面这样准确的形容: 一个分布式的实时文档存储

Oracle性能分析6:数据访问方式之索引扫描

这节将介绍各种索引扫描方式,在了解了各种索引扫描方式的特点后,你就可以判断你的执行计划中使用的扫描方式是否正确,并可以针对获取的信息作出改进. 索引唯一扫描 在下面的场景中使用相等条件时,数据库使用索引唯一扫描. 1)查询条件中包含唯一索引中的所有列时: 2)查询条件使用主键约束列时. 下面是一个实际的例子,在表historyalarm中创建如下唯一索引: create unique index idx_historyalarm$queryid on historyalarm(queryid)

西门子PLC学习笔记十五-(数据块及数据访问方式)

一.数据块 数据块是在S7 CPU的存储器中定义的,用户可以定义多了数据块,但是CPU对数据块数量及数据总量是有限制的. 数据块与临时数据不同,当逻辑块执行结束或数据块关闭,数据块中的数据是会保留住的. 数据块分共享数据块.背景数据块.用户自定义数据块,下面分别介绍. 1.共享数据块(全局数据块) 其用于存储全局数据,所有逻辑块(OB.FC.FB)都可以访问共享数据块中的数据. 2.背景数据块(私有存储区) 其用做功能块(FB)的"存储器".FB的参数和静态变量安排在它的背景数据块中.

执行计划-数据访问方式(全表扫描与4种索引的方式)

执行计划 Oracle执行计划的相关概念: Rowid:系统给oracle数据的每行附加的一个伪列,包含数据表名称,数据库id,存储数据库id以及一个流水号等信息,rowid在行的生命周期内唯一. Recursive sql:为了执行用户语句,系统附加执行的额外操作语句,譬如对数据字典的维护等. Row source(行源):oracle执行步骤过程中,由上一个操作返回的符合条件的行的集合. Predicate(谓词):where后的限制条件. Driving table(驱动表):又称为连接的

Oracle性能分析5:数据访问方式之索引结构和扫描方式介绍

上篇文章讲述了全扫描,这篇文章将介绍索引的结构和扫描方式,在后面将开始讲述每一种扫描方式. 当Oracle通过索引检索具体的一列或多列的列值时,就会执行索引扫描.首先我们来看看索引节点包含的数据. 索引节点包含的数据 索引可以被创建在表的单列或者多列上,索引中包含了这些列的值.rowid和一些其它信息,我们关心的只有列值和rowid.由于索引带有列值,应此如果你的SQL语句只涉及到索引的列,那么Oracle就只从索引本身检索列值,而不需要访问表.如果查询涉及到索引列以外的列,Oracle就需要使