ADO.NET 是一组向 .NET 程序员公开数据访问服务的类。ADO.NET 为创建分布式数据共享应用程序提供了一组丰富的组件。它提供了对关系数据、XML 和应用程序数据的访问,因此是 .NET Framework 中不可缺少的一部分。ADO.NET 支持多种开发需求,包括创建由应用程序、工具、语言或 Internet 浏览器使用的前端数据库客户端和中间层业务对象。
(1) 打开数据库连接
ADO.NET Connection对象:
using SD=System.Data; using MSA=System.Data.OleDb; using SWF=System.Windows.Forms; ... string sConnect; sConnect = string.Format(“Provider={0};Data Source={1}{2}”, “Provider=Microsoft.Jet.OLEDB.4.0;”, System.AppDomain.CurrentDomain.BaseDirectory, “Sales.mdb”); MSA.OleDbConnection dbConn; dbConn = new MSA.OleDbConnection(sConnect); dbConn.Open(); SWF.MessageBox.Show( dbConn.State.ToString() ); |
(2) 执行查询和取回数据
Command and Reader对象:
string sql; BankCustomer c; sql = "Select * From Customers Order By LastName Asc, FirstName Asc;"; MSA.OleDbCommand dbCmd; dbCmd = new MSA.OleDbCommand(sql, dbConn); MSA.OleDbDataReader dbReader; dbReader = dbCmd.ExecuteReader(); while (dbReader.Read()) { c = new BankCustomer(dbReader["FirstName"].ToString(), dbReader["LastName"].ToString(), System.Convert.ToDecimal(dbReader["AcctBalance"])); Globals.Customers.Add(c); } |
(3) 关闭数据库连接
关闭reader 和connection:
dbReader.Close(); dbConn.Close(); SWF.MessageBox.Show( dbConn.State.ToString() ); |
异常处理
使用try-catch-finally 来保证收尾工作,数据库关闭,资源被释放等等
OleDbConnection dbConn = null; OleDbDataReader dbReader = null; try { dbConn = new OleDbConnection(sConnect); dbConn.Open(); ... } catch(Exception ex) { // see defensive programming webcast... ... } finally { try{ dbReader.Close(); } catch{…} try{ dbConn.Close(); } catch{…} } |
ADO.NET 体系结构
ADO.NET 基于Data Provider,Data Provider 封装特定数据库的细节信息
Data Provider
.NET 可以支持多种数据提供者:
- Providers for SQL Server and Oracle
- Support for OLEDB & ODBC
对象模型
不同数据库之间
- “相同”的编程模型,不管使用何种数据库
- 不同的数据库连接字符串
- 不同的名称空间和类:
System.Data.SqlClient.SqlConnection
System.Data.OracleClient.OracleConnection
System.Data.Odbc.OdbcConnection
etc.
Connection 字符串格式
- Connection strings 对于不同的数据库来说是不同的,格式是数据库提供厂商定义的。现在还没有一个很好的文档包括所有的格式
- 哪里去寻找帮助?
http://www.connectionstrings.com
http://www.carlprothman.net/Default.aspx?tabid=81
Executive 概要
几种访问数据库的方式:
- ExecuteScalar——只返回一个值:
string sql; sql = string.Format(“Select AcctBalance From Customers Where CID={0};”, cid); SQL.SqlCommand dbCmd; dbCmd = new SQL.SqlCommand(sql, dbConn); decimal balance; balance = System.Convert.ToDecimal( dbCmd.ExecuteScalar() ); |
2. ExecuteReader
- ExecuteReader产生一个DataReader对象
- DataReader = forward-only, read-only cursor
- 没被关闭之前都保持数据库的连接
string sql = “Select * From Customers;”; SQL.SqlCommand dbCmd = new SQL.SqlCommand(sql, dbConn); SQL.SqlDataReader dbReader = dbCmd.ExecuteReader(); while ( dbReader.Read() ) { ... } |
3. DataSets——另一个.NET 集合类
- 特别适合象表格形式存储数据
- 简单填充,传递,显示在GUI中
为什么使用DataSet?
- DataSet = 非连接的记录集
DataSet是服务器端填充为结果的数据拷贝
Dataset 在客户端运行和处理
DataSet可以重新连接数据库用于更新数据
- 好处:
减少DB服务器的负担
关闭连接后离线工作 - 对于分布式程序是非常重要的…
填充DataSet
使用DataAdapter对象,当DataSet被填充之后,与数据库服务器的连接就关闭了!
string sql = “Select * From Customers;”; SQL.SqlCommand dbCmd = new SQL.SqlCommand(sql, dbConn); SQL.SqlDataAdapter dbAdapter = new SQL.SqlDataAdapter(dbCmd); System.Data.DataSet ds; ds = new System.Data.DataSet(); dbConn.Open(); dbAdapter.Fill(ds); dbConn.Close(); |
使用DataSet——For each record…
foreach(System.Data.DataRow row in ds.Tables["Table"].Rows) { c = new BankCustomer(row["FirstName"].ToString(), row["LastName"].ToString(), System.Convert.ToDecimal(row["AcctBalance"])); Globals.Customers.Add(c); // add to global collection } |
绑定到DataGrid
DataSet可以被绑定到DataGrid控件,写一行代码完成显示!
this.dataGrid1.SetDataBinding(ds, “Table”); |
DataSets像数据库
- 无限制的表空间
- 可以被查询,排序,更新
- 支持视图,关系,约束
// fill DataSet with entire Sales database! string sql ="Select * From Customers; " + "Select * From Orders; " + "Select * From OrderItems; " + "Select * From Products;"; . . . dbConn.Open(); dbAdapter.Fill(ds); dbConn.Close(); |
DataSets —写入数据库…
DataSets允许非连接的修改,客户端应用程序重新连接后更新
SQL.SqlCommandBuilder dbCmdBuilder; dbCmdBuilder = new SQL.SqlCommandBuilder(dbAdapter); ds = (System.Data.DataSet) this.dataGrid1.DataSource; dbConn.Open(); dbAdapter.Update(ds); dbConn.Close(); |
小心: 非连接容易引起很多的冲突…
4. ExecuteNonQuery——写入数据库
通过SQL动作:插入,更新和删除来对数据库进行写操作
string sql; int rows; sql = string.Format(“Delete From Customers Where...”); SQL.SqlCommand dbCmd; dbCmd = new SQL.SqlCommand(sql, dbConn); dbConn.Open(); rows = dbCmd.ExecuteNonQuery(); dbConn.Close(); if (rows != 1) throw new System.ApplicationException(“Delete failed?!”); |
参数化查询
sql = "Select * From Customers Where CID=@CID Order By LastName Asc,FirstName Asc;"; SQL.SqlCommand dbCmd; dbCmd = new SQL.SqlCommand(sql, dbConn); dbCmd.Parameters.Add("@CID", SqlDbType.BigInt); dbCmd.Parameters[0].Value = 1; dbReader = dbCmd.ExecuteReader(); |
调用存储过程
SQL Server中的存储过程
Create PROCEDURE GetCustomer (@CID BigInt) AS Select FirstName,LastName,AcctBalance From Customers Where CID = @CID RETURN |
调用:
SQL.SqlCommand dbCmd =dbConn.CreateCommand(); dbCmd.CommandText = "GetCustomer"; dbCmd.CommandType = CommandType.StoredProcedure; dbCmd.Parameters.Add("@CID", SqlDbType.BigInt); dbCmd.Parameters[0].Value = 1; dbReader = dbCmd.ExecuteReader(); |
Transaction中执行查询
Connection对象的BeginTransaction来创建一个Transaction对象
SQL.SqlTransaction txn = dbConn.BeginTransaction(); string strSQL = "INSERT INTO Customers VALUES(100,'Hui','Yu',1000000,1000000,'01-Jan-2005','money')"; SQL.SqlCommand dbCmd; dbCmd = new SQL.SqlCommand(strSQL, dbConn,txn); int intRecord = dbCmd.ExecuteNonQuery(); if(intRecord ==1) { SWF.MessageBox.Show( "Update Successful");txn.Commit(); } else { SWF.MessageBox.Show( "Update Failed"); txn.Rollback(); } |