ADO.NET を使用した単純なデータ アプリケーションの作成

Note

データセットと関連クラスは、アプリケーションがデータベースから切断されている間にアプリケーションがメモリ内のデータを操作できるようにする、2000 年代初期からのレガシ .NET Framework テクノロジです。 これらが特に役立つのは、ユーザーがデータを変更し、変更をデータベースに戻して保持できるようにするアプリケーションです。 データセットは非常に優れたテクノロジであることが証明されていますが、新しい .NET アプリケーションでは Entity Framework Core を使用することをお勧めしています。 Entity Framework には、オブジェクト モデルとして表形式データを操作する、より自然な方法が用意されており、よりシンプルなプログラミング インターフェイスが備わっています。

データベースのデータを処理するアプリケーションの作成では、接続文字列の定義、データの挿入、ストアド プロシージャの実行などの基本的なタスクを実行します。 このトピックでは、Visual C# または Visual Basic と ADO.NET を使用して、単純な Windows フォームの "フォーム オーバー データ" アプリケーション内からデータベースと対話する方法について説明します。 データセット、LINQ to SQL、Entity Framework を含むすべての .NET データ テクノロジでは、最終的にこの記事に記載されている手順とよく似た手順を実行します。

この記事では、データベースから迅速にデータを取得する簡単な方法について説明します。 アプリケーションで重要でない方法でデータを変更し、データベースを更新する必要がある場合は、Entity Framework の使用と、データ バインディングの使用を考慮して、ユーザー インターフェイス コントロールを基になるデータの変更に自動的に同期することを検討する必要があります。

重要

コードをシンプルにするため、運用環境で使用する例外処理は含まれていません。

Note

このチュートリアルの完全なコードは、Visual Studio ドキュメントの GitHub リポジトリの C# および Visual Basic にあります。

前提条件

アプリケーションの作成には、次が必要です:

  • .NET デスクトップ開発データの保存と処理のワークロードがインストールされた Visual Studio。 これらをインストールするには、Visual Studio インストーラーを開き、変更する Visual Studio のバージョンの横にある [変更] (または [その他]>[変更] ) を選択します。

  • SQL Server Express LocalDB。 SQL Server Express LocalDB がない場合は、SQL Server のダウンロード ページからインストールできます。

このトピックは、Visual Studio IDE の基本的な機能を理解していて、Windows フォーム アプリケーションの作成、そのプロジェクトへのフォームの追加、フォームへのボタンなどのコントロールの追加、コントロールのプロパティの設定、およびシンプルなイベントのコード記述ができることを前提としています。 これらのタスクに問題がある場合は、このチュートリアルを開始する前に、「Visual Studio で Visual Basic を使用して Windows フォーム アプリを作成する」チュートリアルまたは「Visual Studio で C# を使用して Windows フォーム アプリを作成する」チュートリアルを完了してください。

サンプル データベースを設定する

次の手順に従ってサンプル データベースを作成します。

  1. Visual Studio で、 [サーバー エクスプローラー] ウィンドウを開きます。

  2. [データ接続] を右クリックし、 [新しい SQL Server データベースの作成] を選択します。

  3. [サーバー名] テキスト ボックスに「 (localdb)\mssqllocaldb」と入力します。

  4. [新しいデータベース名] テキスト ボックスに「Sales」と入力し、 [OK] を選択します。

    空の Sales データベースが作成され、サーバー エクスプローラーの [データ接続] ノードに追加されます。

  5. Sales データ接続を右クリックし、 [新しいクエリ] を選択します。

    クエリ エディター ウィンドウが開きます。

  6. Sales Transact-SQL スクリプトをクリップボードにコピーします。

  7. T-SQL スクリプトをクエリ エディターに貼り付け、 [実行] ボタンを選択します。

    しばらくすると、クエリの実行が完了し、データベース オブジェクトが作成されます。 データベースには、Customer と Orders という 2 つのテーブルが含まれています。 これらのテーブルには最初はデータが含まれていませんが、作成したアプリケーションを実行するときにデータを追加できます。 データベースには、4 種類のシンプルなストアド プロシージャもあります。

フォームを作成してコントロールを追加する

  1. Windows フォーム アプリ (.NET Framework) テンプレートを使用して C# または Visual Basic プロジェクトを作成し、SimpleDataApp という名前を付けます。

    Visual Studio は、Form1 という名前の空の Windows フォームを含めた、いくつかのファイルとプロジェクトを作成します。

  2. 2 つの Windows フォームをプロジェクトに追加し、合計 3 つのフォームに次の名前を付けます。

    • ナビゲーション

    • NewCustomer

    • FillOrCancel

  3. 各フォームに、次の図に示されるように、テキスト ボックス、ボタン、および他のコントロールを追加します。 各コントロールに、テーブルを示すプロパティを設定します。

    注意

    グループ ボックス、およびラベル コントロールは明確性を追加しますが、コードでは使用されません。

    Navigation フォーム

    ナビゲーション ダイアログ ボックス

Navigation フォームのコントロール プロパティ
ボタン Name = btnGoToAdd
ボタン Name = btnGoToFillOrCancel
ボタン Name = btnExit

NewCustomer フォーム

新しい顧客を追加して注文を作成する

NewCustomer フォームのコントロール プロパティ
TextBox Name = txtCustomerName
TextBox Name = txtCustomerID

Readonly = True
ボタン Name = btnCreateAccount
NumericUpdown DecimalPlaces = 0

Maximum = 5000

Name = numOrderAmount
DateTimePicker Format = Short

Name = dtpOrderDate
ボタン Name = btnPlaceOrder
ボタン Name = btnAddAnotherAccount
ボタン Name = btnAddFinish

FillOrCancel フォーム

注文の入力または取り消し

FillOrCancel フォームのコントロール プロパティ
TextBox Name = txtOrderID
ボタン Name = btnFindByOrderID
DateTimePicker Format = Short

Name = dtpFillDate
DataGridView Name = dgvCustomerOrders

Readonly = True

RowHeadersVisible = False
ボタン Name = btnCancelOrder
ボタン Name = btnFillOrder
ボタン Name = btnFinishUpdates

接続文字列を保存する

アプリケーションがデータベースの接続を開くとき、アプリケーションは接続文字列にアクセスする必要があります。 各フォームで文字列を手動で入力することを回避するため、プロジェクトの App.config ファイルに文字列を保存し、アプリケーションの任意のフォームから呼び出された場合にこの文字列を返すメソッドを作成します。

接続文字列を見つけるには、サーバー エクスプローラーSales データ接続を右クリックし、 [プロパティ] を選択します。 ConnectionString プロパティを見つけ、Ctrl+A キーを使用して文字列を選択し、Ctrl+C キーを使用してクリップボードにコピーします。

  1. C# を使用している場合は、ソリューション エクスプローラーで、プロジェクトの [プロパティ] ノードを展開し、Settings.settings ファイルを開きます。 Visual Basic を使用している場合は、ソリューション エクスプローラー[すべてのファイルを表示] をクリックし、 [My Project] ノードを展開して、Settings.settings ファイルを開きます。

  2. [名前] 列に、「connString」と入力します。

  3. [種類] ボックスの一覧にある [(接続文字列)] を選択します。

  4. [スコープ] ボックスの一覧にある [アプリケーション] を選択します。

  5. [値] 列に、(引用符を除く) 接続文字列を入力し、変更を保存します。

    Settings.settings の接続文字列のスクリーンショット

注意

実際のアプリケーションでは、「接続文字列と構成ファイル」で説明されているように、接続文字列を安全に保存する必要があります。

フォームのコードを記述する

このセクションでは、各フォームの動作の概要を簡単に説明します。 また、フォーム上のボタンをクリックしたときの内部ロジックを定義するコードも提供します。

Navigation フォームはアプリケーションを実行すると開きます。 [Add an account] ボタンは NewCustomer フォームを開きます。 [Fill or cancel orders] ボタンは FillOrCancel フォームを開きます。 [Exit] ボタンは、アプリケーションを閉じます。

Navigation フォームをスタートアップ フォームに設定

C# を使用している場合、ソリューション エクスプローラー Program.cs を開き、Application.Run の行を Application.Run(new Navigation()); に変更します。

Visual Basic を使用している場合、ソリューション エクスプローラーで、 [プロパティ] ウィンドウを開き、 [アプリケーション] タブを選択して、 [スタートアップ フォーム] の一覧から SimpleDataApp.Navigation を選択します。

自動生成されたイベント ハンドラーを作成する

Navigation フォームの 3 つのボタンをダブルクリックして、空のイベント ハンドラー メソッドを作成します。 ボタンをダブルクリックすると、ボタン クリックによってイベントを発生させるための自動生成されたコードもデザイナー コード ファイルに追加されます。

Note

デザイナーでダブルクリック アクションをスキップし、コードをコピーしてコード ファイルに貼り付けるだけの場合は、イベント ハンドラーを適切なメソッドに設定することを忘れないでください。 これは、 [プロパティ] ウィンドウで行うことができます。 [イベント] タブに切り替え (稲妻のツール バー ボタンを使用)、クリック ハンドラーを探します。

Navigation フォーム ロジックのコードを追加する

Navigation フォームのコード ページで、次のコードに示すように、3 つのボタン クリック イベント ハンドラーのメソッド本体を完成させます。

/// <summary>
/// Opens the NewCustomer form as a dialog box,
/// which returns focus to the calling form when it is closed. 
/// </summary>
private void btnGoToAdd_Click(object sender, EventArgs e)
{
    Form frm = new NewCustomer();
    frm.Show();
}

/// <summary>
/// Opens the FillorCancel form as a dialog box. 
/// </summary>
private void btnGoToFillOrCancel_Click(object sender, EventArgs e)
{
    Form frm = new FillOrCancel();
    frm.ShowDialog();
}

/// <summary>
/// Closes the application (not just the Navigation form).
/// </summary>
private void btnExit_Click(object sender, EventArgs e)
{
    this.Close();
}

注意

このチュートリアルのコードは、C# と Visual Basic で使用できます。 このページのコード言語を C# と Visual Basic の間で切り替えるには、各コード例の上部にあるコード言語スイッチャーを使用します。

NewCustomer フォーム

顧客名を入力し [Create Account] ボタンを選択すると、NewCustomer フォームは、顧客アカウントを作成し、SQL Server は新しい顧客 ID として IDENTITY 値を返します。 数量と注文日を指定して [Place Order] ボタンを選択すると、この新しいアカウントの注文を設定できます。

自動生成されたイベント ハンドラーを作成する

4 つのボタンをそれぞれダブルクリックして、NewCustomer フォームの各ボタンに空のクリック イベント ハンドラーを作成します。 ボタンをダブルクリックすると、ボタン クリックによってイベントを発生させるための自動生成されたコードもデザイナー コード ファイルに追加されます。

NewCustomer フォーム ロジックのコードを追加する

NewCustomer フォーム ロジックを完成させるには、次の手順を実行します。

  1. System.Data.SqlClient 名前空間をスコープ内に入れて、メンバーの名前を完全修飾する必要がないようにします。

    using System.Data.SqlClient;
    
  2. 次のコードに示すように、クラスにいくつかの変数とヘルパー メソッドを追加します。

    // Storage for IDENTITY values returned from database.
    private int parsedCustomerID;
    private int orderID;
    
    /// <summary>
    /// Verifies that the customer name text box is not empty.
    /// </summary>
    private bool IsCustomerNameValid()
    {
        if (txtCustomerName.Text == "")
        {
            MessageBox.Show("Please enter a name.");
            return false;
        }
        else
        {
            return true;
        }
    }
    
    /// <summary>
    /// Verifies that a customer ID and order amount have been provided.
    /// </summary>
    private bool IsOrderDataValid()
    {
        // Verify that CustomerID is present.
        if (txtCustomerID.Text == "")
        {
            MessageBox.Show("Please create customer account before placing order.");
            return false;
        }
        // Verify that Amount isn't 0.
        else if ((numOrderAmount.Value < 1))
        {
            MessageBox.Show("Please specify an order amount.");
            return false;
        }
        else
        {
            // Order can be submitted.
            return true;
        }
    }
    
    /// <summary>
    /// Clears the form data.
    /// </summary>
    private void ClearForm()
    {
        txtCustomerName.Clear();
        txtCustomerID.Clear();
        dtpOrderDate.Value = DateTime.Now;
        numOrderAmount.Value = 0;
        this.parsedCustomerID = 0;
    }
    
  3. 次のコードに示すように、4 つのボタンクリック イベント ハンドラーのメソッド本体を完成させます。

    /// <summary>
    /// Creates a new customer by calling the Sales.uspNewCustomer stored procedure.
    /// </summary>
    private void btnCreateAccount_Click(object sender, EventArgs e)
    {
        if (IsCustomerNameValid())
        {
            // Create the connection.
            using (SqlConnection connection = new SqlConnection(Properties.Settings.Default.connString))
            {
                // Create a SqlCommand, and identify it as a stored procedure.
                using (SqlCommand sqlCommand = new SqlCommand("Sales.uspNewCustomer", connection))
                {
                    sqlCommand.CommandType = CommandType.StoredProcedure;
    
                    // Add input parameter for the stored procedure and specify what to use as its value.
                    sqlCommand.Parameters.Add(new SqlParameter("@CustomerName", SqlDbType.NVarChar, 40));
                    sqlCommand.Parameters["@CustomerName"].Value = txtCustomerName.Text;
    
                    // Add the output parameter.
                    sqlCommand.Parameters.Add(new SqlParameter("@CustomerID", SqlDbType.Int));
                    sqlCommand.Parameters["@CustomerID"].Direction = ParameterDirection.Output;
    
                    try
                    {
                        connection.Open();
    
                        // Run the stored procedure.
                        sqlCommand.ExecuteNonQuery();
    
                        // Customer ID is an IDENTITY value from the database.
                        this.parsedCustomerID = (int)sqlCommand.Parameters["@CustomerID"].Value;
    
                        // Put the Customer ID value into the read-only text box.
                        this.txtCustomerID.Text = Convert.ToString(parsedCustomerID);
                    }
                    catch
                    {
                        MessageBox.Show("Customer ID was not returned. Account could not be created.");
                    }
                    finally
                    {
                        connection.Close();
                    }
                }
            }
        }
    }
    
    /// <summary>
    /// Calls the Sales.uspPlaceNewOrder stored procedure to place an order.
    /// </summary>
    private void btnPlaceOrder_Click(object sender, EventArgs e)
    {
        // Ensure the required input is present.
        if (IsOrderDataValid())
        {
            // Create the connection.
            using (SqlConnection connection = new SqlConnection(Properties.Settings.Default.connString))
            {
                // Create SqlCommand and identify it as a stored procedure.
                using (SqlCommand sqlCommand = new SqlCommand("Sales.uspPlaceNewOrder", connection))
                {
                    sqlCommand.CommandType = CommandType.StoredProcedure;
    
                    // Add the @CustomerID input parameter, which was obtained from uspNewCustomer.
                    sqlCommand.Parameters.Add(new SqlParameter("@CustomerID", SqlDbType.Int));
                    sqlCommand.Parameters["@CustomerID"].Value = this.parsedCustomerID;
    
                    // Add the @OrderDate input parameter.
                    sqlCommand.Parameters.Add(new SqlParameter("@OrderDate", SqlDbType.DateTime, 8));
                    sqlCommand.Parameters["@OrderDate"].Value = dtpOrderDate.Value;
    
                    // Add the @Amount order amount input parameter.
                    sqlCommand.Parameters.Add(new SqlParameter("@Amount", SqlDbType.Int));
                    sqlCommand.Parameters["@Amount"].Value = numOrderAmount.Value;
    
                    // Add the @Status order status input parameter.
                    // For a new order, the status is always O (open).
                    sqlCommand.Parameters.Add(new SqlParameter("@Status", SqlDbType.Char, 1));
                    sqlCommand.Parameters["@Status"].Value = "O";
    
                    // Add the return value for the stored procedure, which is  the order ID.
                    sqlCommand.Parameters.Add(new SqlParameter("@RC", SqlDbType.Int));
                    sqlCommand.Parameters["@RC"].Direction = ParameterDirection.ReturnValue;
    
                    try
                    {
                        //Open connection.
                        connection.Open();
    
                        // Run the stored procedure.
                        sqlCommand.ExecuteNonQuery();
    
                        // Display the order number.
                        this.orderID = (int)sqlCommand.Parameters["@RC"].Value;
                        MessageBox.Show("Order number " + this.orderID + " has been submitted.");
                    }
                    catch
                    {
                        MessageBox.Show("Order could not be placed.");
                    }
                    finally
                    {
                        connection.Close();
                    }
                }
            }
        }
    }
    
    /// <summary>
    /// Clears the form data so another new account can be created.
    /// </summary>
    private void btnAddAnotherAccount_Click(object sender, EventArgs e)
    {
        this.ClearForm();
    }
    
    /// <summary>
    /// Closes the form/dialog box.
    /// </summary>
    private void btnAddFinish_Click(object sender, EventArgs e)
    {
        this.Close();
    }
    

FillOrCancel フォーム

FillOrCancel フォームは、Order ID (注文 ID) を入力して [Find Order] のボタンをクリックしたときに、Order (注文) を戻すクエリを実行します。 戻された行は読み取り専用なデータ グリッドに表示されます。 [Cancel Order] ボタンを選択すると、注文をキャンセル (X) としてマークできます。また [Fill Order] ボタンを選択すると、注文を満たした (F) としてマークできます。 [Find Order] ボタンをもう一度選択すると、更新された行が表示されます。

自動生成されたイベント ハンドラーを作成する

ボタンをダブルクリックして、FillOrCancel フォームの 4 つのボタンに空のクリック イベント ハンドラーを作成します。 ボタンをダブルクリックすると、ボタン クリックによってイベントを発生させるための自動生成されたコードもデザイナー コード ファイルに追加されます。

FillOrCancel フォーム ロジックのコードを追加する

FillOrCancel フォーム ロジックを完成させるには、次の手順を実行します。

  1. 次の 2 つの名前空間をスコープ内に入れて、メンバーの名前を完全修飾する必要がないようにします。

    using System.Data.SqlClient;
    using System.Text.RegularExpressions;
    
  2. 次のコードに示すように、クラスに変数とヘルパー メソッドを追加します。

    // Storage for the order ID value.
    private int parsedOrderID;
    
    /// <summary>
    /// Verifies that an order ID is present and contains valid characters.
    /// </summary>
    private bool IsOrderIDValid()
    {
        // Check for input in the Order ID text box.
        if (txtOrderID.Text == "")
        {
            MessageBox.Show("Please specify the Order ID.");
            return false;
        }
    
        // Check for characters other than integers.
        else if (Regex.IsMatch(txtOrderID.Text, @"^\D*$"))
        {
            // Show message and clear input.
            MessageBox.Show("Customer ID must contain only numbers.");
            txtOrderID.Clear();
            return false;
        }
        else
        {
            // Convert the text in the text box to an integer to send to the database.
            parsedOrderID = Int32.Parse(txtOrderID.Text);
            return true;
        }
    }
    
  3. 次のコードに示すように、4 つのボタンクリック イベント ハンドラーのメソッド本体を完成させます。

    /// <summary>
    /// Executes a t-SQL SELECT statement to obtain order data for a specified
    /// order ID, then displays it in the DataGridView on the form.
    /// </summary>
    private void btnFindByOrderID_Click(object sender, EventArgs e)
    {
        if (IsOrderIDValid())
        {
            using (SqlConnection connection = new SqlConnection(Properties.Settings.Default.connString))
            {
                // Define a t-SQL query string that has a parameter for orderID.
                const string sql = "SELECT * FROM Sales.Orders WHERE orderID = @orderID";
    
                // Create a SqlCommand object.
                using (SqlCommand sqlCommand = new SqlCommand(sql, connection))
                {
                    // Define the @orderID parameter and set its value.
                    sqlCommand.Parameters.Add(new SqlParameter("@orderID", SqlDbType.Int));
                    sqlCommand.Parameters["@orderID"].Value = parsedOrderID;
    
                    try
                    {
                        connection.Open();
    
                        // Run the query by calling ExecuteReader().
                        using (SqlDataReader dataReader = sqlCommand.ExecuteReader())
                        {
                            // Create a data table to hold the retrieved data.
                            DataTable dataTable = new DataTable();
    
                            // Load the data from SqlDataReader into the data table.
                            dataTable.Load(dataReader);
    
                            // Display the data from the data table in the data grid view.
                            this.dgvCustomerOrders.DataSource = dataTable;
    
                            // Close the SqlDataReader.
                            dataReader.Close();
                        }
                    }
                    catch
                    {
                        MessageBox.Show("The requested order could not be loaded into the form.");
                    }
                    finally
                    {
                        // Close the connection.
                        connection.Close();
                    }
                }
            }
        }
    }
    
    /// <summary>
    /// Cancels an order by calling the Sales.uspCancelOrder
    /// stored procedure on the database.
    /// </summary>
    private void btnCancelOrder_Click(object sender, EventArgs e)
    {
        if (IsOrderIDValid())
        {
            // Create the connection.
            using (SqlConnection connection = new SqlConnection(Properties.Settings.Default.connString))
            {
                // Create the SqlCommand object and identify it as a stored procedure.
                using (SqlCommand sqlCommand = new SqlCommand("Sales.uspCancelOrder", connection))
                {
                    sqlCommand.CommandType = CommandType.StoredProcedure;
    
                    // Add the order ID input parameter for the stored procedure.
                    sqlCommand.Parameters.Add(new SqlParameter("@orderID", SqlDbType.Int));
                    sqlCommand.Parameters["@orderID"].Value = parsedOrderID;
    
                    try
                    {
                        // Open the connection.
                        connection.Open();
    
                        // Run the command to execute the stored procedure.
                        sqlCommand.ExecuteNonQuery();
                    }
                    catch
                    {
                        MessageBox.Show("The cancel operation was not completed.");
                    }
                    finally
                    {
                        // Close connection.
                        connection.Close();
                    }
                }
            }
        }
    }
    
    /// <summary>
    /// Fills an order by calling the Sales.uspFillOrder stored
    /// procedure on the database.
    /// </summary>
    private void btnFillOrder_Click(object sender, EventArgs e)
    {
        if (IsOrderIDValid())
        {
            // Create the connection.
            using (SqlConnection connection = new SqlConnection(Properties.Settings.Default.connString))
            {
                // Create command and identify it as a stored procedure.
                using (SqlCommand sqlCommand = new SqlCommand("Sales.uspFillOrder", connection))
                {
                    sqlCommand.CommandType = CommandType.StoredProcedure;
    
                    // Add the order ID input parameter for the stored procedure.
                    sqlCommand.Parameters.Add(new SqlParameter("@orderID", SqlDbType.Int));
                    sqlCommand.Parameters["@orderID"].Value = parsedOrderID;
    
                    // Add the filled date input parameter for the stored procedure.
                    sqlCommand.Parameters.Add(new SqlParameter("@FilledDate", SqlDbType.DateTime, 8));
                    sqlCommand.Parameters["@FilledDate"].Value = dtpFillDate.Value;
    
                    try
                    {
                        connection.Open();
    
                        // Execute the stored procedure.
                        sqlCommand.ExecuteNonQuery();
                    }
                    catch
                    {
                        MessageBox.Show("The fill operation was not completed.");
                    }
                    finally
                    {
                        // Close the connection.
                        connection.Close();
                    }
                }
            }
        }
    }
    
    /// <summary>
    /// Closes the form.
    /// </summary>
    private void btnFinishUpdates_Click(object sender, EventArgs e)
    {
        this.Close();
    }
    

アプリケーションのテスト

アプリケーションを実行し、いくつかの顧客と注文を作成して、すべてが期待した通りに動作していることを確認してください。 データベースが変更で更新されたことを確認するには、サーバー エクスプローラー[テーブル] ノードを開き、 [顧客][注文] ノードを右クリックして、 [テーブル データの表示] を選択します。