Note
DataSet クラスと関連クラスは、アプリケーションがデータベースから切断されている間にアプリケーションがメモリ内のデータを操作できるようにする、2000 年代初頭のレガシ .NET Framework テクノロジです。 このテクノロジは、ユーザーがデータを変更し、変更をデータベースに保持できるアプリに特に役立ちます。 データセットは実証済みの成功したテクノロジですが、新しい .NET アプリケーションには Entity Framework Core を使用することをお勧めします。 Entity Framework は、オブジェクト モデルとして表形式データを操作するより自然な方法を提供し、よりシンプルなプログラミング インターフェイスを備えています。
データベース内のデータを操作するアプリケーションを作成するときは、通常、接続文字列の定義、データの挿入、ストアド プロシージャの実行などのタスクを実行します。 この記事に従うと、Visual C# または Visual Basic と ADO.NET を使用して、 データ (FOD) Windows フォーム アプリケーション経由でフォーム内からデータベースを操作する方法を確認できます。 データセット、SQL への LINQ (Language-Integrated クエリ)、Entity Framework を含むすべての .NET データ テクノロジは、最終的に、この記事に示されている手順に似た手順を実行します。
この記事では、データベースからデータをすばやく取得する方法について説明します。 アプリケーションで非一般的な方法でデータを変更し、データベースを更新する必要がある場合は、Entity Framework とデータ バインディングの使用を検討してください。 これにより、ユーザー インターフェイス コントロールは、基になるデータの変更と自動的に同期できます。
このチュートリアルの完全なコードにアクセスするには、 C# と Visual Basic の Visual Studio ドキュメント GitHub リポジトリを参照してください。
Important
コードをシンプルに保つために、運用環境に対応した例外処理は含まれません。
Prerequisites
.NET デスクトップ開発 と データ ストレージと処理 ワークロードがインストールされている Visual Studio。 インストールするには、Visual Studio インストーラーを開き、 変更 する Visual Studio のバージョンの横にある [変更] を選択します。
SQL Server Express LocalDB。 SQL Server Express LocalDB がない場合は、SQL Server ダウンロード ページからインストール。
この記事では、Visual Studio IDE の基本的な機能について理解していることを前提としています。 また、Windows フォーム アプリケーションの作成、プロジェクトへのフォームの追加、フォームへのボタンやその他のコントロールの追加、コントロールのプロパティの設定、および単純なイベントのコーディングが可能であることを前提としています。 これらのタスクに慣れていない場合は、このチュートリアルを開始する前に、 Visual Studio で C# を使用して Windows フォーム アプリを作成するチュートリアル または Visual Studio で Windows フォーム アプリを作成 するチュートリアルを完了してください。
サンプル データベースを設定する
次の手順に従って、サンプル データベースを作成します。
Visual Studio で、Server Explorer ウィンドウを開きます。
[データ接続] を右クリックし、[新しい SQL Server データベースの作成] を選択します。
[サーバー名] に「(localdb)\mssqllocaldb」と入力します。
[ 新しいデータベース名] に 「Sales」と入力し、[ OK] を選択します。
Visual Studio は、サーバー エクスプローラーの [データ接続] ノードの下に空の Sales データベースを作成します。
Sales データ接続を右クリックし、[新しいクエリ] を選択します。
クエリ エディター ウィンドウが開きます。
Sales Transact-SQL スクリプト をクリップボードにコピーします。
T-SQL スクリプトをクエリ エディター ウィンドウに貼り付け、[ 実行] を選択します。
しばらくすると、クエリの実行が完了し、データベース オブジェクトが作成されます。 データベースには、Customer と Orders の 2 つのテーブルが含まれています。 これらのテーブルには最初はデータが含まれていませんが、作成したアプリケーションを実行するときにデータを追加できます。 データベースには、5 つの基本的なストアド プロシージャも含まれています。
フォームを作成してコントロールを追加する
Windows フォーム アプリ (.NET Framework) テンプレートを使用して C# または Visual Basic プロジェクトを作成し、SimpleDataApp という名前を付けます。
Visual Studio では、プロジェクトと、 Form1 という名前の空の Windows フォームを含む複数のファイルが作成されます。
ソリューション エクスプローラーで、2 つの Windows フォームをプロジェクトに追加して、合計 3 つのフォームを作成し、次の名前を付けます。
Navigation
NewCustomer
FillOrCancel
フォームごとに、次の図に示すテキスト ボックス、ボタン、およびその他のコントロールを追加します。 各コントロールに対して、テーブルに記述されるプロパティを設定します。
Note
グループ ボックスとラベル コントロールはわかりやすくしますが、コードでは使用されません。
Navigation フォーム
ナビゲーション フォームのコントロール
テキストを制御する コントロールの種類 コントロールのプロパティ [アカウントの追加] Button Name = btnGoToAdd 注文の入力または取り消し Button Name = btnGoToFillOrCancel Exit Button Name = btnExit NewCustomer フォーム
NewCustomer フォームのコントロール
ラベル/コントロールテキスト コントロールの種類 コントロールのプロパティ 顧客名 TextBox Name = txt顧客名 顧客ID TextBox Name = txtCustomerID
ReadOnly = True (読み取り専用 = 真)アカウントを作成する Button Name = btnCreateAccount 注文金額 NumericUpdown Name = numOrderAmount
DecimalPlaces = 0 (小数点の位置)
最大 = 5000注文日 DateTimePicker Name = dtpOrderDate
フォーマット = ショート注文 Button Name = btnPlaceOrder Finish Button Name = btnAddFinish 別のアカウントを追加する Button Name = btnAddAnotherAccount FillOrCancel フォーム
FillOrCancel フォームのコントロール
ラベル/コントロールテキスト コントロールの種類 コントロールのプロパティ 注文識別子 TextBox Name = txtOrderID 注文の検索 Button Name = btnFindByOrderID 注文を入力する場合... DateTimePicker Name = dtpFillDate
フォーマット = ショート(None) DataGridView Name = dgvCustomerOrders
ReadOnly = True (読み取り専用 = 真)
RowHeadersVisible = False注文の取り消し Button Name = btnCancelOrder 注文の入力 Button Name = btnFillOrder Finish Button Name = btnFinishUpdates
接続文字列を格納する
アプリケーションがデータベースへの接続を開こうとすると、アプリケーションは接続文字列にアクセスできる必要があります。 各フォームで文字列を手動で入力する必要を回避するには、プロジェクトの App.config ファイルに文字列を格納します。 次に、アプリケーション内の任意のフォームからメソッドが呼び出されたときに文字列を返すメソッドを作成します。
接続文字列を検索するには:
サーバー エクスプローラーで、 Sales データ接続を右クリックし、[ プロパティ] を選択します。
接続文字列プロパティを見つけて、その文字列値をクリップボードにコピーします。
プロジェクトに接続文字列を格納するには:
ソリューション エクスプローラーで、プロジェクトの種類に応じて、次のいずれかの手順を実行します。
C# プロジェクトの場合は、プロジェクトの下にある [プロパティ ] ノードを展開し、 Settings.settings ファイルを開きます。
Visual Basic プロジェクトの場合は、[ すべてのファイルを表示] を選択し、[ マイ プロジェクト ] ノードを展開して 、Settings.settings ファイルを開きます。
[名前] 列に「connString」と入力します。
[ 種類 ] ボックスの一覧で 、 (接続文字列) を選択します。
[スコープ] の一覧で、[アプリケーション] を選択します。
[値 列に接続文字列を入力し (外部引用符を使用せずに)、変更を保存します。
Caution
実際のアプリケーションでは、「接続文字列と構成ファイル 説明されているように、接続文字列を安全に格納する必要があります。 セキュリティを最大限に高めるには、接続文字列にパスワードを格納することに依存しない認証方法を使用します。 たとえば、オンプレミスの SQL Server データベースの Windows 認証などです。 詳細については、「 接続文字列の保存と編集」を参照してください。
フォームのコードを記述する
このセクションでは、各フォームの機能の概要について簡単に説明します。 また、フォーム上のボタンを選択するときに基になるロジックを定義するコードも提供します。
ナビゲーション フォーム
アプリケーションを実行するとナビゲーション フォームが開き、次のボタンが含まれます。
アカウントを追加する: NewCustomer フォームを 開きます。
注文の入力または取り消し: FillOrCancel フォームを 開きます。
終了: アプリケーションを閉じます。
ナビゲーション フォームをスタートアップ フォームにする
C# プロジェクトの場合:
ソリューション エクスプローラー で、Program.csを開きます。
Application.Run
行を次の値に変更します。Application.Run(new Navigation());
Visual Basic プロジェクトの場合:
ソリューション エクスプローラーで、プロジェクトを右クリックし、[プロパティ] を選択します。
プロジェクト デザイナーで、[アプリケーション] タブを選択し、[スタートアップ] オブジェクトの一覧で [ナビゲーション] を選択します。
ナビゲーション フォームの自動生成されたイベント ハンドラーを作成する
空のイベント ハンドラー メソッドを作成するには、ナビゲーション フォームの 3 つのボタンをそれぞれダブルクリックします。 ボタンをダブルクリックすると、デザイナー コード ファイルに自動生成されたコードが追加されます。これにより、ボタンの選択によってイベントが発生します。
デザイナーでダブルクリック アクションを使用するのではなく、コードファイルに直接コードをコピーして貼り付ける場合は、イベント ハンドラーを適切なメソッドに設定してください。
フォームのコード ファイルの [プロパティ ] ウィンドウで、稲妻ツール バー ボタンを使用して [ イベント ] タブに切り替えます。
Click プロパティを検索し、その値が正しいイベント ハンドラー メソッドであることを確認します。
ナビゲーション フォーム ロジックのコードを追加する
ナビゲーション フォームのコード ページで、次のコードに示すように、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();
}
新規顧客フォーム
顧客名を入力し、[ アカウントの作成 ] ボタンを選択すると、NewCustomer フォームによって顧客アカウントが作成され、SQL Server は新しい顧客 ID として IDENTITY 値を返します。 その後、金額と注文日を指定し、[注文の配置] ボタンを選択して、新しいアカウントの 注文を行 うことができます。
NewCustomer フォームの自動生成されたイベント ハンドラーを作成する
4 つの各ボタンをダブルクリックして、NewCustomer フォームの各ボタンに空の Click イベント ハンドラーを作成します。 ボタンをダブルクリックすると、デザイナー コード ファイルに自動生成されたコードも追加されます。これにより、ボタンの選択によってイベントが発生します。
NewCustomer フォーム ロジックのコードを追加する
NewCustomer フォーム ロジックを完了するには、次の手順に従います。
System.Data.SqlClient
名前空間をスコープに取り込み、メンバーの名前を完全に修飾する必要がないようにします。
いくつかの変数とヘルパー メソッドをクラスに追加します。
// 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; }
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 フォームは、注文 ID を入力したときに注文を返すクエリを実行し、[ 注文の検索 ] ボタンを選択します。 返された行は、読み取り専用のデータ グリッドに表示されます。 [注文の取り消し] ボタンを選択した場合は注文を 取り消 し (X) に設定するか、[ 注文の入力] ボタンを選択した場合は注文を [完了] (F) としてマークできます。 [ 注文の検索 ] ボタンをもう一度選択すると、更新された行が表示されます。
FillOrCancel フォームの自動生成されたイベント ハンドラーを作成する
ボタンをダブルクリックして、FillOrCancel フォームの 4 つのボタンの空の Click イベント ハンドラーを作成します。 ボタンをダブルクリックすると、デザイナー コード ファイルに自動生成されたコードも追加されます。これにより、ボタンの選択によってイベントが発生します。
FillOrCancel フォーム ロジックのコードを追加する
FillOrCancel フォーム ロジックを完了するには、次の手順に従います。
メンバーの名前を完全修飾する必要がなくなるように、次の 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; } }
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(); }
アプリケーションをテストする
アプリケーションを実行し、いくつかの顧客と注文を作成して、すべてが期待どおりに動作していることを確認します。
データベースが自分の変更で更新されたことを確認するには:
サーバー エクスプローラーで [テーブル] ノードを開きます。
[顧客] ノードと [注文] ノードを右クリックし、[テーブル データの表示] を選択します。