第五讲 ADO.NET最佳实践

*ADO.NET架构
$数据提供程序:
1、SQL Server .NET 数据提供程序
2、OLE DB .NET 数据提供程序
3、ODBC .NET 数据提供程序
4、用于 Oracle 的 .NET 数据提供程序

$对象概述:
Connection类:在代码和容纳数据的数据存储之间提供了基本的连接
Command类:用于描述SQL语句或者通过其Connection类执行的存储过程
DataReader:从数据源中获取只读的数据流
DataAdapter:功能最强大、更复杂的对象,可以读取、改变数据源

*ADO.NET连接最佳实践
使用连接池
用 DataAdapter 优化连接
始终关闭 Connection 和 DataReader
在 C# 中使用 “Using” 语句
处理异常
安全连接

%为什么为连接池?
创建连接所花费的时间与资源并不是无价值的。
Connection pools可以使在特定页面运行过后,连接能够保持下来

%ADO.NET中的连接池
1、如果使用的是 OleDbConnection 类,则连接池将由提供程序自动处理,您不必自己进行管理。
2、如果使用的是 SqlConnection 类,则连接池被隐式管理,但也提供选项允许您自己管理池。
在连接字符串中指定:
pooling =true;//默认为true
connection lifetime=5;//默认为0
min pool size=1;//默认为0
max pool size=50“;//默认为100
例如
String strConUsePool="Server=localhost;Integrated Security=SSPI;DataBase=myDataBase;pooling=true;Connection lifetime=5"

%用 DataAdapter 优化连接
1、DataAdapter 的 Fill 和 Update 方法在连接关闭的情况下自动打开为相关命令属性指定的连接。如果 Fill 或 Update 方法打开了连接

,Fill 或 Update 将在操作完成的时候关闭它。为了获得最佳性能,仅在需要时将与数据库的连接保持为打开。同时,减少打开和关闭多操

作连接的次数。
2、如果只执行单个的 Fill 或 Update 方法调用,建议允许 Fill 或 Update 方法隐式打开和关闭连接。如果对 Fill 和/或 Update 调用

有很多,建议显式打开连接,调用 Fill 和/或 Update,然后显式关闭连接。


%始终关闭 Connection 和 DataReader
完成对 Connection 或 DataReader 对象的使用后,总是显式地关闭它们。尽管垃圾回收最终会清除对象并因此释放连接和其他托管资源,

但垃圾回收仅在需要时执行。
%在 C# 中使用 “Using” 语句
using 语句在离开自己的作用范围时,会自动调用被“使用”的对象的 Dispose。

%连接异常
-DataException 类:表示使用 ADO.NET 组件发生错误时引发的异常
-DBConcurrencyException 类:在更新操作过程中受影响的行数等于零时,由 DataAdapter 所引发的异常。
-SqlException 类:当 SQL Server 返回警告或错误时引发的异常。无法继承此类。

%SqlException 类
#属性
#任何时候只要 SQL Server .NET 数据提供程序遇到服务器生成的错误,就会创建该类。SqlException 始终包含至少一个 SqlError 实例。
#严重程度等于或小于 10 的消息是信息性消息,它们指示由用户输入信息中的错误所导致的问题。严重程度 11 至 16 的消息是由用户生成的,可以由用户更正。严重程度 17 至 25 的消息指示软件或硬件错误。当发生严重程度为 17、18 或 19 的错误时,虽然可能无法执行特定语句,但仍可以继续工作。
#当严重程度等于或小于 19 时,SqlConnection 保持打开状态。当严重度等于或大于 20 时,服务器通常会关闭 SqlConnection。但是,用户可以重新打开连接并继续操作。在这两种情况下,执行命令的方法都会生成 SqlException。

*使用命令最佳实践
-Command对象的使用
-使用 SqlCommand 的最佳实践
-使用 Prepare 方法
-显式指定架构和元数据
-测试 Null
-把 Null 作为参数值传递
-执行事务

-Command对象的使用
  方法   描述
Cancel 取消数据命令的执行
CreateParameter 创建一个新的参数
ExecuteNonQuery 执行命令并返回受影响的行数
ExecuteReader 执行命令并返回生成的DataReader
ExecuteScalar 执行查询并返回结果集中的第一行的第一列
ExecuteXmlReader 执行命令并返回生成的XMLReader
Prepare 在数据源上创建一个准备好的命令版本
ResetCommandTimeOut 将CommandTimeOut属性重置为默认值

-DataReader
^当数据命令返回结果集时,用DataReader 来检索数据
^DataReader对象返回一个来自数据命令的只读的、只能向前的数据流
^内存中每次仅有一个数据行,因此开销很少

-ExecuteScalar 和 ExecuteNonQuery
^如果想返回像 Count(*)、Sum(Price) 或 Avg(Quantity) 的结果那样的单值,可以使用 Command.ExecuteScalar。
^因为单独一步就能完成,所以 ExecuteScalar 不仅简化了代码,还提高了性能;要是使用 DataReader 就需要两步才能完成(即,ExecuteReader + 取值)。
^使用不返回行的 SQL 语句时,例如修改数据(例如INSERT、UPDATE 或 DELETE)或仅返回输出参数或返回值,请使用 ExecuteNonQuery。这避免了用于创建空 DataReader 的任何不必要处理。

-使用 SqlCommand 的最佳实践
.存储过程是SQLServer数据库的一个重要特色
.存储过程执行效率比SQL文本命令要高的多
.提高了程序的复用性
.存储过程中可以使用变量和条件
.可以在存储过程中使用参数
.如果调用存储过程,将 SqlCommand 的 CommandType 属性指定为 StoredProcedure 的 CommandType。这样通过将该命令显式标识为存储过程,就不需要在执行之前分析命令。


-使用 Prepare 方法
.对于重复作用于数据源的参数化命令,Command.Prepare 方法能提高性能。
.对于一些数据源(例如 SQL Server 2000),命令是隐式优化的,不必调用 Prepare。
.对于其他(例如 SQL Server 7.0)数据源,Prepare 会比较有效。

-测试 Null
.如果表(在数据库中)中的列允许为空,就不能测试参数值是否“等于”空。
.SELECT * FROM Customers
WHERE ((LastName = @LastName) OR (LastName IS NULL AND @LastName IS NULL))
-把 Null 作为参数值传递
.对数据库的命令中,当把空值作为参数值发送时,不能使用 null(Visual Basic.NET 中为 Nothing)。而需要使用 DBNull.Value。 

-事务处理
ADO.NET 的事务模型已经更改。
.在 ADO 中,当调用 StartTransaction 时,调用之后的任何更新操作都被视为是事务的一部分。
.但是,在 ADO.NET 中,当调用 Connection.BeginTransaction 时,会返回一个 Transaction 对象,需要把它与 Command 的 Transaction 属性联系起来。这种设计可以在一个单一连接上执行多个根事务。
.如果未将 Command.Transaction 属性设置为一个针对相关的 Connection 而启动的 Transaction,那么 Command 就会失败并引发异常。

-使用 DataReader、DataSet、DataAdapter
DataSet是一种代表关系数据的内存驻留结构

-执行以下操作使用 DataSet:
.在结果的多个离散表之间进行导航。
.操作来自多个数据源(例如,来自多个数据库、一个 XML 文件和一个电子表格的混合数据)的数据。
.在各层之间交换数据或使用 XML Web 服务。
.重用同样的行组,以便通过缓存获得性能改善(例如排序、搜索或筛选数据)。
.每行执行大量处理。

-对于下列情况,要在应用程序中使用DataReader:
.不需要缓存数据。
.要处理的结果集太大,内存中放不下。
.一旦需要以只进、只读方式快速访问数据。

-DataReader 的常见问题:
.在访问相关 Command 的任何输出参数之前,必须关闭 DataReader。完成读数据之后总是要关闭DataReader。
.当访问列数据时,使用类型化访问器
.一个单一连接每次只能打开一个 DataReader。
.默认情况下,DataReader 每次 Read 时都要把整行加载到内存。这允许在当前行内随机访问列。如果不需要这种随机访问,为了提高性能,就把 CommandBehavior.SequentialAccess 传递给 ExecuteReader 调用
.如果已经完成读取来自 DataReader 的数据,但仍然有大量挂起的未读结果,就在调用 DataReader 的 Close 之前先调用 Command 的 Cancel。

-二进制大对象 (BLOB)
.用 DataReader 检索二进制大对象 (BLOB) 时,应该把 CommandBehavior.SequentialAccess 传递给 ExecuteReader 方法调用。
.SequentialAccess 将 DataReader 的行为设置为只加载请求的数据。然后还可以使用 GetBytes 或 GetChars 控制每次加载多少数据。

-其他技巧
.避免自动增量值冲突(GUID)
.检查开放式并发冲突
.多线程编程
.仅在需要的时候才用 COM Interop 访问 ADO

posted @ 2009-03-15 19:56  teacherzj  阅读(239)  评论(0编辑  收藏  举报