【C#】データベース SQL Server 2022 Express(無償版)へアクセスしてみよう【入門】

C#ライン

C#プログラミングでデータベースSQL Serverを操作

Windowsフォームアプリを作成し、無料版データベース「SQL Server 2022」を利用してデータの表示、追加、削除、更新を行う簡単なプログラミングをご紹介します。データベース管理システム(Database Management System,DBMS)を利用することで「データ操作がこんなに便利なんだ」ということが実感できるかと思います。ぜひこの機会にプログラミングでデータベースを操作する方法を試してみましょう!

■「SQL Server 2022」のインストール

本記事ではインストール手順の説明は省略します。下記の記事で分かりやすく説明していますので参考にしてください。

 https://sumiox.com/sqlserver-install/

■「SQL Server Management Studio」のインストール

本記事ではインストール手順の説明は省略します。下記の記事で分かりやすく説明していますので参考にしてください。

 SSMSダウンロードページ

■「SQL Server Management Studio」を起動する

Windowsのスタートボタンをクリックし「Microsoft SQL Server Tools 19」→「SQL Server Management Studio 19」をクリックします。

「サーバーへの接続」画面が表示されるので「接続(C)」ボタンをクリックし接続を開始します。

接続に成功すると管理ツールの左側にある「オブジェクトエクスプローラー」が表示され、一番上の階層にSQL Server名称、バージョン、ユーザー名が確認できます。

■データベースの作成

オブジェクトエクスプローラーの中に「データベース」があるので、それを右クリックして「新しいデータベース」を選択します。

「新しいデータベース」画面が表示されるので「データベース名」に「TestDB」を入力し「OK」ボタンをクリックします。

これでオブジェクトエクスプローラーの「データベース」項目の中に「TestDB」が作成されました。

■テーブルの作成

次にTestDBデータベースの中に「TestTBL」テーブルを作ります。「TestTBL」項目の中に「テーブル」がありますので、それを右クリックし「新規作成」→「テーブル(T)…」を選択します。

すると右側の画面にテーブル作成画面が表示されるので、Id,Name,Birthdayとういう名前の3つの列(カラム)を作成します。

列名データ型NULLを許可
Idint
Namenvarchar(50)
Birthdaydate

Idの行を選択した状態で右クリックし「主キーの設定」をすると鍵マークが表示されます。また、Idの列のプロパティで「IDENTITY」の項目の「IDである」を「はい」にします。

以上の設定が終わったらテーブル名を保存します。画面上部のメニュー「ファイル」→「Table_1を保存」を選択するとダイアログが表示されるので「TestTBL」と入力し「OK」ボタンをクリックします。

このままではまだテーブルが更新されていません。オブジェクトエクスプローラーの上の方の更新マークをクリックすると「テーブル」の中に「ado.TestTBL」が表示されテーブルが作成されたことが確認できます。

■テーブルにデータ追加

今度は、TestTBLテーブルにデータを追加してみます。
オブジェクトエクスプローラーの「テーブル」→「ado.TestTBL」を選択し右クリックし、「上位200行の編集」を選択します。

右画面にデータの入力画面が表示されます。

それでは下記のようにデータを入力してみましょう。Id列はテーブル作成時にプロパティ設定「IDENTITY」の「IDである」を「はい」に設定しましたので自動入力になっているので入力は不要です。このデータ入力画面ではある行を編集し、次の行に移動すると、その時点でデータベースにその行のデータが書き換わります。保存の操作は必要ありません。

■データベースのバックアップの作成

ここまで作成したら、今作ったデータベースのバックアップを作成しておきましょう。それを使えばデータベースをもとに戻したり、データベースをほかのコンピュータ上のSQL Serverにコピーしたりといった作業ができるようになります。バックアップを作成するには、オブジェクトエクスプローラーの「TestDB」→「タスク」→「バックアップ(B)…」を選択します。

下図のような「データベースのバックアップ-TestDB」の画面が表示されます。

バックアップ先を「ディスク」にし保存先を確認し右下の「OK」ボタンをクリックします。バックアップに成功すると下記のメッセージが表示されますので「OK」ボタンをクリックします。

バックアップしたデータベースの復元をしてみましょう。「TestDB」→「タスク」→「復元」→「データベース(D)…」を選択します。

下図のような「データベースの復元-TestDB」が表示されますので「OK」ボタンをクリックします。

復元に成功すると下図のように「復元に成功しました」とメッセージが表示されますので「OK」ボタンをクリックします。

ちなみに復元しようとしているデータベースが使用中だと「復元に失敗しました」と下図のようなメッセージが表示されますので一度「SQL Server Management Studio」を閉じて再起動してから実行してみましょう。

■「Visual Studio 2022」でプロジェクト作成

これからC#で先ほど作成したデータベースのテーブルに接続し内容を表示するプログラムを作っていきます。統合開発環境の「Visual Studio 2022」起動し「新しいプロジェクトの作成(N)」を選択します。

検索ボックスに「フォーム アプリケーション」(半角スペース有)を入力しプロジェクトのテンプレートを絞り込みます。「Windows フォーム アプリケーション(.NET Framework)」でC#が表示されているテンプレートを選択し画面右下の「次へ」ボタンをクリックします。似たような名前のテンプレートが複数ありますので注意しましょう。

「新しいプロジェクトを構成します」の画面が表示されるのでプロジェクト名を「TestDBsqlsv」を入力し、場所で作成するアプリのフォルダを確認し「作成(C)」をクリックします。

新規プロジェクト画面が表示されますのでメニューの「デバッグ(D)」→「デバッグ開始(S)」をクリックし一度実行させます。Form1画面が立ち上がりますので×で閉じます。問題ないことを確認し「ファイル」→「すべて保存」でプロジェクトのファイルをすべて保存します。

■フォームにコントロールを配置する

メニューの「表示(V)」→「ツールボックス(X)」を選択し画面にツールボックスを表示させます。そのツールボックスの上の部分をドラッグすると中央に配置する位置が表示されますので指定の位置にドロップします。

下図はフォームの右側にツールボックスを配置したものです。

Windowsフォームアプリケーション開発では、中央のフォームにツールボックスからコントロールなどをドラッグアンドドロップすることでフォーム画面を構築します。下図を参考にコントロールの種類ごとにドラッグアンドドロップし配置します。コントロールのプロパティウインドウでコントロールの名前などを変更できます。

種類NameText
ButtonbuttonConnect接続
DataGridViewdataGridView1
BindingSourcebindingSource1

■「接続」するコードを記述

フォームの何もない部分をダブルクリックすると、コード編集画面に切り替わり「Form_Load」というメソッドが作成されます。フォームデザイン画面に戻って「接続」ボタンをダブルクリックすると、今度は「buttonConnect_Click」メソッドが作成されます。

下記コードを記述します。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Data.SqlClient;  //(1)

namespace TestDBsqlsv
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e) //(2)
        {
            dataGridView1.DataSource = bindingSource1;  //(3)
        }

        private void buttonConnect_Click(object sender, EventArgs e) //(4)
        {
            string connectString =   //(5)
                "Integrated Security=SSPI;" +
                "Initial Catalog=TestDB;" +
                @"Data Source=localhost";
            string selectString = "select * from TestTBL"; //(6)

            try
            {
                SqlDataAdapter DataAdapter = new SqlDataAdapter(  
                    selectString, connectString);       //(7)
                DataTable dataTable = new DataTable();  //(8)
                DataAdapter.Fill(dataTable);            //(9)
                bindingSource1.DataSource = dataTable;  //(10)
            } catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "エラー");   //(11)
            }
        }
    }
}

(1)では、System.Data.SqlClient名前空間のクラスを短縮したコードで記述できるようにすます。この名前空欄にはSQL Serverにアクセスするためのソフトウェア部品が用意されています。
(2)のForm1_Loadメソッドは起動時に呼び出されます。
(3)はdataGridView1のDataSourceプロパティにbindingSource1を設定しています。この設定はプロパティウインドウでもできますがプロパティ設定をコードで記述することで見通しをよくします。
(4)は「接続」ボタンを押すと呼び出されます。
(5)は「接続文字列」とよばれるものです。「Integrated Security=SSPI」は、SQL ServerへのログインにWindowsの認証情報を使うことを示しています。SSPIはSecurity Support Provider Interfaceの略です。「Initial Catalog=TestDB」はデータベース名(TestDB)の指定です。「Data Source=localhost」はSQL Serverのサーバー名の指定です。「Data Source=localhost\testdb」とした場合、\の右側testdbがインスタンス名となります。(今回インスタンス名は無し)
(6)の「select * from TestTBL」はSQLというデータベース言語です。テーブル(TestTBL)から(from)すべての行(*)を取得する(select)という指示になります。SQLをselectString変数へ代入します。
(7)でSqlDataAdapterはSQL ServerにアクセスするためのDataAdapterです。DataAdapterはADO.NETにおいて、デーtベースに接続してデータを操作する役目を担うクラスです。DataAdapterはFillメソッドなどを持ちADO.NETの日接続オブジェクトであるDataTableなどにデータを注入できます。
(8)でDataTableクラスのインスタンスであるdataTableを作ります。
(9)でデータを注入します。
(10)でbindingSource1のDataSourceプロパティにdataTableを代入します。

これで下図のようにオブジェクトが連kwつされ、ユーザーにSQL Serverないのデータが見えるようになるわけです。

(7)から(10)では様々な実行時エラーが生じるかの世があります。それをtry~catch文で囲みエラーが生じた場合に(11)でエラーメッセージを出すようにしています。

例えば、(5)で記述した「Data Source=localhost」を「Data Source=localhost\testdb」というようにインスタンス名を指定した場合、下図のようなエラーメッセージが表示されます。

■切断、提出、再読み込みのボタンを追加

今までは「接続」ボタンだけでしたが、今度は「切断」「提出」「再読み込み」のボタンを追加します。

種類NameText
ButtonbuttonDisonnect切断
ButtonbuttonSubmit提出
ButtonbuttonReload再読み込み

■「接続」「Form_Load」などのコードの修正

それでは「切断」「提出」「再読み込み」のクリックイベントを作成する前に、今まで作成したコードを先に修正します。下記コードが修正後の全文コードです。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Data.SqlClient;

namespace TestDBsqlsv
{
    public partial class Form1 : Form
    {
        private SqlDataAdapter DataAdapter; //(12)

        private bool ConnectedValue; //(13)
        private bool Connected       //(14)
        {
            get {return ConnectedValue; }
            set
            {
                ConnectedValue = value;
                buttonConnect.Enabled = !value;
                buttonDisconnect.Enabled = value;
                buttonSubmit.Enabled = value;
                buttonReload.Enabled = value;
            }
        }                            //(14)

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            dataGridView1.DataSource = bindingSource1;
            Connected = false;   //(15)
        }

        private void buttonConnect_Click(object sender, EventArgs e)
        {
            string connectString =
                "Integrated Security=SSPI;" +
                "Initial Catalog=TestDB;" +
                @"Data Source=localhost";
            string selectString = "select * from TestTBL";

            try
            {
                DataAdapter = new SqlDataAdapter(    //(16)
                    selectString, connectString);
                SqlCommandBuilder commandbuilder =   //(17)
                    new SqlCommandBuilder(DataAdapter);
                DataTable dataTable = new DataTable();
                DataAdapter.Fill(dataTable);         
                bindingSource1.DataSource = dataTable;
                Connected = true;          //(18)
            } catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "エラー");
            }
        }
    }
}

(12)でDataAdapteをローカルからクラスレベルの変数宣言に移します。
(13)と(14)はデータベース(SQL Server)に接続しているかどうかを保持するための変数です。(14)のConnectedはプロパティを追加しています。プロパティにしているのは、この値が変わった場合にボタンの有効/無効を切り替えたいためです。接続していない状態では「接続」ボタンだけを有効にし、接続したら「接続」を無効にし「切断」「提出」「再読み込み」を有効にします。「切断」「提出」「再読み込み」は接続していないときに押すと実行時エラーとなってしまうためです。
(15)は起動時に呼び出されるForm_Loadメソッドで「Connected = false」とすることで、起動直後には「切断」「提出」「再読み込み」が無効になります。
(16)は(12)に宣言文を移しましたので「SqlDataAdapte」は削除します。
(17)は「接続」ボタンを呼び出されるメソッドで、今回追記した分です。データベースの操作コマンド(SQL)を自動で作らせるためです。
(18)は接続が完了したら「Connected」をtrueにします・

■「切断」「提出」「再読み込み」のコードを記述

フォームデザイン画面に戻り、「切断」「提出」「再読み込み」のそれぞれのボタンをクリックしbuttonDisconnect_Click、buttonSubmit_Click、buttonReload_Clickの3つのメソッドを作成しその中にコードを記述していきます。

     private void buttonDisconnect_Click(object sender, EventArgs e) //(19)
      {
          bindingSource1.DataSource = null;
          DataAdapter.Dispose();
          dataGridView1.Update();
          Connected = false;
      }

      private void buttonSubmit_Click(object sender, EventArgs e)  //(20)
      {
          DataAdapter.Update((DataTable)
              bindingSource1.DataSource);
      }

      private void buttonReload_Click(object sender, EventArgs e)  //(21)
      {
          buttonDisconnect_Click(sender, e);
          buttonConnect_Click(sender, e);
      }

(19)は「切断」のボタンをクリックしたときのイベントハンドラです。bindingSource1のDataSourceが何も指していない状態にし、DataAdapterの内容を破棄し、dataGridView1を更新します。これでdataGridView1は何も表示しない状態になります。最後にConnectedをfalseにしボタンの有効/無効を切り替えます。
(20)の「提出」ボタンはこのプログラムが持つデータを。データベースサーバーに提出するものです。「提出」ボタンを押すまでは入力したデータはデータベースサーバーに送信されません。SqlDataAdapterクラスを継承したDataAdapterクラスのUpdateメソッドにbindingSource1のDataSourceをDataTable方に変換したものを与えることで、このプログラムが持つデータのうち、変更された部分だけをデータベースサーバーに送信しています。
(21)の「再読み込み」ボタンは切断ボタンと接続ボタンをクリックしています。

■dataGridView1の操作方法

コードを書き終わったら実際に動かしてみましょう。このプログラムで、データの表示、更新、追加、削除という一通りの操作ができます。メニューの「▶開始」ボタンをクリックしてアプリを起動させます。

「接続」ボタンをクリックするとSQL Serverに接続しデータが表示されます。

最終行のName列に「吉田三郎」、Birthday列に「1987/12/4」と入力し下矢印キーを押してカーソルを移動させます。id列は自動採番されますので入力は不要です。

「提出」ボタンと「再読み込み」ボタンををクリックすると「吉田三郎」のidが「5」になったことが分かります。(注 id4は動作テストのときに削除)

では今後は、今登録したid「4」のデータをDeleteボタンで削除します。

「提出」ボタンをクリ九すると変更がSQL Serverのデータベースに反映されます。「再読み込み」ボタンををクリックし表示を更新すると削除されたことが確認できます。

最後に「切断」ボタンをクリックするとSQL Serverデータベースとの接続を終了します。

■ラベルとテキストボックスを追加する

dataGridViewコントロールは複数のデータを一覧表示させるのに便利ですが1件のデータを操作するには不向きです。ラベル(Label)コントロールやテキストボックス(TestBox)コントロールなどには「データバインド」と呼ばれる機能があり、データベースに結び付ける(バインド)ことができるようになっています。下記のように4つのコントロールを追加しましょう。Id列に結び付けるlabelId、Name列に結び付けるtextBoxName、Birthday列に結び付けるtextBoxBirthday 、そしてデータを操作を補助するbindingNavigator1コントロールです。

種類NameText
LabelLabelIdlabel1
TextBoxtextBoxName
TextBoxtextBoxBirthday
BindingNavigatorbindingNavigator1

bindingNavigator1はDockプロパティを「None」にしておきましょう。

■ラベル、テキストボックス、バインドナビゲーターのコードを記述
下記のようにForm1_Loadメソッド、buttonConnect_Clickメソッド、buttonDisconnect_Clickメソッドに追記します。

        private void Form1_Load(object sender, EventArgs e)
        {
            dataGridView1.DataSource = bindingSource1;
            bindingNavigator1.BindingSource = bindingSource1; //(22)
            Connected = false;
        }

       private void buttonConnect_Click(object sender, EventArgs e)
       {
           string connectString =
               "Integrated Security=SSPI;" +
               "Initial Catalog=TestDB;" +
               @"Data Source=localhost";
           string selectString = "select * from TestTBL";

           try
           {
               DataAdapter = new SqlDataAdapter(
                   selectString, connectString);
               SqlCommandBuilder commandbuilder =
                   new SqlCommandBuilder(DataAdapter);
               DataTable dataTable = new DataTable();
               DataAdapter.Fill(dataTable);
               bindingSource1.DataSource = dataTable;
               labelId.DataBindings.Add("Text",        //(23)
                   bindingSource1, "Id");              //(23)
               textBoxName.DataBindings.Add("Text",    //(23)
                   bindingSource1, "Name");            //(23)
               textBoxBirthday.DataBindings.Add("Text",//(23)
                   bindingSource1, "Birthday", true);  //(23)
               Connected = true;
           } catch (Exception ex)
           {
               MessageBox.Show(ex.Message, "エラー");
           }
       }

       private void buttonDisconnect_Click(object sender, EventArgs e)
       {
           labelId.DataBindings.Clear();     //(24)
           textBoxName.DataBindings.Clear();   //(24)
           textBoxBirthday.DataBindings.Clear();  //(24)
           labelId.Text = "";                     //(24)
           textBoxName.Text = "";                 //(24)
           textBoxBirthday.Text = "";             //(24)
           bindingSource1.DataSource = null;
           DataAdapter.Dispose();
           dataGridView1.Update();
           Connected = false;
       }

(22)はbindingNavigator1のデータソースをbindingSource1に設定します。
(23)は「接続」ボタンクリック時のこーどを追記します。labelIdのTextプロパティにbindingSource1のId列を結び付けます。textBoxNameでは、テキストボックスのTextプロパティにbindingSource1のName列を結び付けます。textBoxBirthdayでは、テキストボックスのTextプロパティにbindingSource1のBirthday列を結び付けます。4番目の引数にtrueにしているのは書式設定を有効にするためです。この設定をすると「yyyy/mm/dd」形式で表示されます。設定しないと「yyyy/mm/dd 00:00:000」のようになってしまいます。
(24)は「切断」ボタンクリック時のコードを追記します。labelId、textBoxNam、textBoxBirthdayのデータバインドを削除(Clear)し、Textプロパティを消します(””).

実行すると下図のように表示されます。

コメント