将 ASP.NET 应用程序连接到 Azure SQL 数据库

已完成

可以通过多种方式从应用程序中连接 Azure SQL 数据库服务中的数据库。 可以为 .NET 应用使用 System.Data.SqlClient 库。

用于高校的 Web 应用必须提取并显示已上传到 SQL 数据库的数据。 在本单元中,你将学习如何从 Web 应用连接数据库并使用 System.Data.SqlClient 库处理数据。

System.Data.SqlClient 库概述

System.Data.SqlClient 库是类型和方法的集合,可用于连接在本地或云中的 SQL 数据库上运行的 SQL Server 数据库。 该库提供了用于检索和维护数据的通用接口。 使用 System.Data.SqlClient 库可以运行 Transact-SQL (T-SQL) 命令、执行事务操作并检索数据。 可以参数化这些操作,以避免与 SQL 注入攻击相关的问题。 如果某个操作失败,System.Data.SqlClient 库会通过专门的异常和错误类来提供任何错误信息。 可以像处理 .NET 应用程序中的任何其他类型的异常一样处理这些异常。

System.Data.SqlClient 库可通过 System.Data.SqlClient NuGet 包获取。

连接到单一数据库

使用 SqlConnection 对象创建数据库连接。 提供一个连接字符串,用于指定数据库的名称和位置、要使用的凭据以及其他与连接相关的参数。 一个典型的单一数据库连接字符串如下所示:

Server=tcp:myserver.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:myserver.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 表中删除给定客户的行。 可以参数化命令。 此示例使用名为 CustID 的参数作为 CustomerID 的值。 将 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()}");
        }
    }
}