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: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 portal でそのデータベースに対する [接続文字列] ページを見るとわかります。

次のコード例では、SqlConnection オブジェクトの作成方法が示されています。

using System.Data.SqlClient;

...

string connectionString = "Server=tcp:myserver.database.windows.net,...";
SqlConnection con = new SqlConnection(connectionString);

接続を開くまで、データベース接続は確立されません。 通常、接続は T-SQL コマンドまたはクエリを実行する直前に開きます。

con.Open();

一部のデータベースでは、限られた数のコンカレント接続しかサポートされていません。 そのため、コマンドの実行を終えて結果を取得したら、接続を閉じて保持しているリソースを解放することをお勧めします。

con.Close();

もう 1 つの一般的な方法は、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 コマンドまたはクエリを指定します。 次の例では、特定の顧客の行を dbo.Orders テーブルから削除する T-SQL DELETE ステートメントが示されています。 コマンドをパラメーター化することができます。 この例では、CustomerID の値に対して CustID という名前のパラメーターが使われています。 SqlCommand オブジェクトの CommandType プロパティを Text に設定する行では、コマンドが T-SQL ステートメントであることが示されています。 T-SQL ステートメントではなく、ストアド プロシージャを実行することができます。 その場合は CommandTypeStoredProcedure に設定します。

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.Customers テーブルと dbo.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 コマンドを実行して、1 行ずつデータをフェッチする方法が示されています。

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()}");
        }
    }
}