將 ASP.NET 應用程式連線到 Azure SQL Database

已完成

有許多不同的方式可以用來從應用程式連線到 Azure SQL Database 服務內的資料庫。 對於 .NET 應用程式,您可以使用 System.Data.SqlClient 程式庫。

該大學的 Web 應用程式必須擷取和顯示您上傳至您 SQL 資料庫的資料。 在此單元中,您會了解如何從 Web 應用程式應用程式連線到資料庫,並使用 System.Data.SqlClient 程式庫來處理資料。

System.Data.SqlClient 程式庫概觀

System.Data.SqlClient 程式庫是類型和方法的集合,可用來連線到在內部部署或雲端 SQL Database 上執行的 SQL Server 資料庫。 該程式庫提供用來擷取和維護資料的一般化介面。 您可以使用 System.Data.SqlClient 程式庫來執行 Transact-SQL (T-SQL) 命令和交易作業,以及擷取資料。 您可以參數化這些作業,以避免 SQL 插入式攻擊的相關問題。 如果作業失敗,System.Data.SqlClient 程式庫會透過特製化例外狀況和錯誤類別來提供錯誤資訊。 處理這些例外狀況的方式,和處理 .NET 應用程式中任何其他類型的例外狀況相同。

System.Data.SqlClient 程式庫可在 System.Data.SqlClient NuGet 套件中取得。

連線到單一資料庫

您會使用 SqlConnection 物件來建立資料庫連線。 您提供指定資料庫名稱和位置的「連接字串」、要使用的認證,以及其他連線相關參數。 單一資料庫的一般連接字串看起來像這樣:

Server=tcp:<server-name>.database.windows.net,1433;Initial Catalog=mydatabase;Persist Security Info=False;User ID=myusername;Password=mypassword;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;

您可以在 Azure 入口網站中適用於您資料庫的 [連接字串] 頁面上,找到您單一資料庫的連接字串。

下列程式碼範例顯示如何建立 SqlConnection 物件:

using System.Data.SqlClient;

...

string connectionString = "Server=tcp:<server-name>.database.windows.net,...";
SqlConnection con = new SqlConnection(connectionString);

直到您開啟連線,才會建立資料庫連線。 您通常會在執行 T-SQL 命令或查詢前才開啟連線。

con.Open();

某些資料庫僅支援有限的並行連線數目。 因此,在您執行完命令並擷取任何結果之後,建議您將連線關閉並釋放任何已保留的資源。

con.Close();

另一個常見的方法是在 using 陳述式中建立連線。 此策略能在 using 陳述式完成時自動關閉連線。 但您也可以明確呼叫 Close 方法。

using (SqlConnection con = new SqlConnection(connectionString))
{
    // Open and Use the connection here
    con.Open();
    ...
}
// Connection is now closed

定義 T-SQL 命令或查詢

建立 SqlCommand 物件來指定要執行的 T-SQL 命令或查詢。 下列範例顯示 T-SQL DELETE 陳述式,其能將指定客戶的資料列從 dbo.Orders 資料表移除。 您可以將命令參數化。 此範例會使用針對 CustomerID 值命名為 CustID 的參數。 將 SqlCommand 物件的 CommandType 屬性設定為 Text 的程式碼行會指出該命令是 T-SQL 陳述式。 您也可以執行預存程序,而不是 T-SQL 陳述式。 在該情況下,您會將 CommandType 設定為 StoredProcedure

SqlCommand deleteOrdersForCustomer = new SqlCommand("DELETE FROM Orders WHERE CustomerID = @custID", con);
deleteOrdersForCustomer.CommandType = CommandType.Text;
string customerID = <prompt the user for a customer to delete>;
deleteOrdersForCustomer.Parameters.Add(new SqlParameter("custID", customerID));

此範例中針對 SqlCommand 建構函式的最後一個參數是要用來執行命令的連線。

下一個範例會顯示將 dbo.Customersdbo.Orders 資料表聯結在一起的查詢,以產生客戶名稱和其訂單的清單。

SqlCommand queryCmd = new SqlCommand(
                    @"SELECT c.FirstName, c.LastName, o.OrderID
                      FROM Customers c JOIN Orders o
                      ON c.CustomerID = o.CustomerID", con);
queryCmd.CommandType = CommandType.Text;

執行命令

如果您的 SqlCommand 物件所參考的 T-SQL 陳述式不會傳回結果集,請使用 ExecuteNonQuery 方法來執行該命令。 如果命令成功,它會傳回被該作業影響的資料列數目。 下一個範例會示範如何執行稍早所示的 deleteOrdersForCustomer 命令。

int numDeleted = deleteOrdersForCustomer.ExecuteNonQuery();

如果您預期執行命令必須花一些時間,您可以使用 ExecuteNonQueryAsync 方法以非同步方式執行該作業。

執行查詢和擷取資料

如果您的 SqlCommand 包含 T-SQL SELECT 陳述式,則必須使用 ExecuteReader 方法來執行它。 此方法會傳回 SqlDataReader 物件,您可以用它來逐一查看結果,並依次處理每個資料列。 您會使用 Read 方法從 SqlReader 物件擷取資料。 如果找到資料列,此方法會傳回 True;如果已經沒有要讀取的資料列,則會傳回 False。 讀取資料列之後,該資料列的資料便可在 SqlReader 物件的欄位中取得。 每個欄位都會具有和原始 SELECT 陳述式中相對應資料行相同的名稱。 不過,每個欄位中的資料都會被擷取為不具類型的 object,因此您必須將它轉換成適當類型才能使用它。 下面的程式碼顯示如何執行稍早前所示的 queryCmd 命令,以一次擷取一個資料列的資料。

SqlDataReader rdr = queryCmd.ExecuteReader();

// Read the data a row at a time
while (rdr.Read())
{
    string firstName = rdr["FirstName"].ToString();
    string lastName = rdr["LastName"].ToString();
    int orderID = Convert.ToInt32(rdr["OrderID"]);

    // Process the data
    ...
}

處理例外狀況和錯誤

當您使用資料庫時,有很多原因會導致發生例外狀況和錯誤。 例如,您可能會嘗試存取已經不存在的資料表。 您可以使用 SqlException 類型來攔截 T-SQL 錯誤。

資料庫中的各種事件或問題可能會觸發例外狀況。 SqlException 物件具有 Errors 屬性,其中包含 SqlError 物件的集合。 這些物件能提供每個錯誤的詳細資料。 下列範例顯示如何攔截 SqlException,並處理其所包含的錯誤。

...
using (SqlConnection con = new SqlConnection(connectionString))
{
    SqlCommand command = new SqlCommand("DELETE FROM ...", con);
    try
    {
        con.Open();
        command.ExecuteNonQuery();
    }
    catch (SqlException ex)
    {
        for (int i = 0; i < ex.Errors.Count; i++)
        {
            Console.WriteLine($"Index # {i} Error: {ex.Errors[i].ToString()}");
        }
    }
}