您的位置:首页 > 其它

ADO.NET最佳实践学习

2008-04-03 02:31 387 查看
ADO.NET架构



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

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

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



ADO.NET中的连接池:
·如果使用的是 OleDbConnection 类,则连接池将由提供程序自动处理,您不必自己进行管理。
·如果使用的是 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";//Integrated Security=SSPI (windows集成方式)
//计算使用连接池的时间
dtStart = DateTime.Now;
for(int i=1;i<=nConNum;i++)
{
using(SqlConnection con = new SqlConnection(strConusePool))
{
con.Open();
con.Close();
}
}
dtEnd = DateTime.Now;
ts = dtEnd-dtStart;
lbUse.Text = ts.Milliseconds.ToString();

始终关闭 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对象的使用:
方法 描述
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 的任何不必要处理。

代码片断:
class ExecuteOptions
{
public SqlDataReader ExecuteReader()
{
SqlConnection con = new SqlConnection("Server=localhost; Integrated Security=SSPI; database=mydatabase; Max Pool Size=75; Min Pool Size=5");
SqlCommand cmdTitle = new SqlCommand("select Username,password,score from scoretable",con);
cmdTitle.CommandType=CommandType.Text;

SqlDataReader dr;
con.Open();
dr =cmdTitle.ExecuteReader(CommandBehavior.CloseConnection);//在执行该命令时,如果关闭关联的DataReader对象,则关联的connection对象也将关闭
return dr;
}
public int ExecuteScalar()
{
SqlConnection con = new SqlConnection("Server=localhost; Integrated Security=SSPI; database=mydatabase;Max Pool Size=75; Min Pool Size=5");
SqlCommand cmdTitleCount = new SqlCommand("select count(*) from scoretable",con);
cmdTitleCount.CommandType=CommandType.Text;
con.Open();
return Convert.ToInt32(cmdTitleCount.ExecuteScalar().ToString());
}
public void ExecuteNonQuery()
{
SqlConnection con = new SqlConnection("Server=localhost; Integrated Security=SSPI; database=mydatabase;Max Pool Size=75; Min Pool Size=5");
SqlCommand cmdUpdateSales = new SqlCommand("Update scoretable set score = score+200 where username='成龙'",con);
cmdUpdateSales.CommandType=CommandType.Text;
con.Open();
cmdUpdateSales.ExecuteNonQuery();
}
public DataSet ExecuteandFill()
{
SqlConnection con = new SqlConnection("Server=localhost; Integrated Security=SSPI; database=mydatabase;Max Pool Size=75; Min Pool Size=5");
SqlDataAdapter da = new SqlDataAdapter("select username, password,score from scoretable",con);
DataSet ds = new DataSet();
con.Open();
da.Fill(ds);
return ds;
}
}

使用 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 就会失败并引发异常。

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

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 控制每次加载多少数据。

思考问题:
·避免自动增量值冲突
·检查开放式并发冲突
·多线程编程
·仅在需要的时候才用 COM Interop 访问 ADO
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: