Ado.net設計模式

鏈接類

鏈接類有固定的使用模式,這是經常使用的樂觀模式: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"];
相關文章
相關標籤/搜索