鏈接類有固定的使用模式,這是經常使用的樂觀模式:html
using (var conn = new SqlConnection(connstr)) { conn.Open(); //執行各類數據庫操做 }
悲觀的、防護性的編程方式,這裏在using語句結尾顯示關閉了鏈接,並捕捉整個using語句的數據庫異常:sql
try { using (var conn = new SqlConnection(connstr)) { conn.Open(); //執行各類數據庫操做 conn.Close(); } } catch (SqlException e) { throw; }
當使用多條語句修改數據庫是,應將全部這些語句看做一個單元,要麼徹底成功修改數據庫(提交),要麼徹底失敗任何一條修改語句都不會被執行(回滾)。要想使用事務,先要引用System.Transactions裝配體。事務的代碼以下所示:數據庫
using (var scope = new TransactionScope()) { using (var conn = new SqlConnection(connstr)) { conn.Open(); // 執行各類數據庫操做 } scope.Complete(); }
在這裏,事務範圍使用了默認構造函數,它意味着TransactionScopeOption.Required、IsolationLevel.Serializable、TimeOut=1分鐘。編程
事務經過使用scope.Complete顯式標記爲完成。缺乏這個調用,事務將被回滾。函數
事務範圍內能夠有多個鏈接,都被看做一個總體。ui
事務的隔離級別:spa
ReadCommitted | 讀取已經提交的數據 |
ReadUncommitted | 讀取尚未提交的數據 |
RepeatableRead | |
Serializable |
打開數據庫鏈接以後,須要定義要執行的命令。對Sql Server可用的命令類型有兩種:文本、和存儲過程。htm
定義文本類型命令的方法以下。由於文本類型的命令是默認值,因此不須要顯式指定命令類型:對象
var sql = "SELECT ContactName FROM Customers"; var cmd = new SqlCommand(sql, conn);
定義存儲過程類型的命令:事務
var cmd = new SqlCommand("CustOrderHist", conn) { CommandType = CommandType.StoredProcedure }; cmd.Parameters.AddWithValue("@CustomerID", "QUICK");
定義了命令以後,須要執行它。根據返回結果不一樣分紅三種執行方法。
ExecuteNonQuery方法通常用於UPDATE,INSERT,或DELETE語句。它執行命令,並返回受影響的行數。
打開鏈接後,添加以下代碼:
var cmd = new SqlCommand("CustOrderHist", conn) { CommandType = CommandType.StoredProcedure }; cmd.Parameters.AddWithValue("@CustomerID", "QUICK"); var rows = cmd.ExecuteNonQuery();
ExecuteReader方法執行命令,並返回一個數據閱讀器對象。在打開鏈接語句以後,添加以下代碼:
var sql = "SELECT ContactName,CompanyName FROM Customers"; var cmd = new SqlCommand(sql, conn); var reader = cmd.ExecuteReader(); while (reader.Read()) { Console.WriteLine("Contact: {0,-20} Company: {1}", reader[0], reader[1]); }
ExecuteScalar執行返回一個標量值的命令。在打開鏈接語句以後,添加以下代碼:
var sql = "SELECT COUNT(*) FROM Customers"; var cmd = new SqlCommand(sql, conn); var custs = (int)cmd.ExecuteScalar(); Console.WriteLine(custs);
ExecuteScalar方法返回一個object對象,須要將其轉化爲實際的類型。
這裏列出兩個例子,使用了Northwind數據庫的Region表。
存儲過程定義以下:
CREATE PROCEDURE RegionUpdate (@RegionID INTEGER, @RegionDescription NCHAR(50)) AS SET NOCOUNT OFF UPDATE Region SET RegionDescription = @RegionDescription WHERE RegionID = @RegionID GO
如前所述,定義一個命令,並添加他的參數和參數值:
var cmd = new SqlCommand("RegionUpdate", conn) { CommandType = CommandType.StoredProcedure }; cmd.Parameters.AddWithValue("@RegionID", 23); cmd.Parameters.AddWithValue("@RegionDescription", "Something"); cmd.ExecuteNonQuery();
存儲過程定義以下:
CREATE PROCEDURE RegionDelete (@RegionID INTEGER) AS SET NOCOUNT OFF DELETE FROM Region WHERE RegionID = @RegionID GO
在命令定義部分,使用SqlParameter構造函數來構造命令參數:
var cmd = new SqlCommand("RegionDelete", conn) { CommandType = CommandType.StoredProcedure }; cmd.Parameters.Add(new SqlParameter("@RegionID", SqlDbType.Int, 0, "RegionID")); cmd.UpdatedRowSource = UpdateRowSource.None;
構造完命令並添加參數定義以後,經過參數名字檢索出參數並設置它的值,而後執行命令:
cmd.Parameters["@RegionID"].Value = 999; cmd.ExecuteNonQuery();
也能夠經過參數位置檢索參數。
下面的例子演示插入一個記錄到數據庫而且返回該記錄的主鍵給調用者。
CREATE PROCEDURE RegionInsert(@RegionDescription NCHAR(50), @RegionID INTEGER OUTPUT)AS SET NOCOUNT OFF SELECT @RegionID = MAX(RegionID)+ 1 FROM Region INSERT INTO Region(RegionID, RegionDescription) VALUES(@RegionID, @RegionDescription) GO
插入過程創造一個新的Region記錄。由於主鍵由數據庫本身生成,這值被做爲一個輸出參數從過程(@RegionID)返回。下面代碼顯示咱們將如何調用RegionInsert存儲過程:
var cmd = new SqlCommand("RegionInsert", conn) { CommandType = CommandType.StoredProcedure }; cmd.Parameters.Add(new SqlParameter("@RegionDescription", SqlDbType.NChar, 50, "RegionDescription")); cmd.Parameters.Add(new SqlParameter("@RegionID", SqlDbType.Int, 0, ParameterDirection.Output, false, 0, 0, "RegionID", DataRowVersion.Default, null)); cmd.UpdatedRowSource = UpdateRowSource.OutputParameters;
第二參數,@RegionID,包括它的參數方向,在這個例子中是Output。代碼的最後一行UpdateRowSource枚舉被用來指明數據將從這個存儲過程經過輸出參數返回。
調用這個存儲過程相似於前面的例子,除了輸出參數是在執行過程以後被讀取:
cmd.Parameters["@RegionDescription"].Value = "South West"; cmd.ExecuteNonQuery(); var newRegionID = (int)cmd.Parameters["@RegionID"].Value;
不能直接實例化一個數據讀取器,只能由相應的命令對象經過ExecuteReader方法返回。
using (var conn = new SqlConnection(connstr)) { conn.Open(); var sql = "SELECT ContactName,CompanyName FROM Customers"; var cmd = new SqlCommand(sql, conn); var reader = cmd.ExecuteReader(); while (reader.Read()) { var contact = reader.GetString(0); var company = reader.GetString(1); Console.WriteLine("'{0}' from {1}", contact, company); } reader.Close(); conn.Close(); }
能夠經過位置或者名稱讀取字段值,而後將返回的object值強制轉換爲合適的數據類型:
var contact = (string)reader[0]; var company = (string)reader["CompanyName"];