2015年9月22日火曜日

SQLiteでDataTableを使ってDataGridViewに表示する

■準備

System.Data.SQLite.dllを追加します。




usingを追加します。
using System.Data.SQLite;

適当なデータを用意します。
今回は、都道府県と県庁データとしときます。
テーブルはこんな感じ。

CREATE TABLE [sample] (
  [pref] TEXT,
  [capital] TEXT,
  PRIMARY KEY(pref)
);




フォームにDataGridViewを配置します。
データを読み込みます。


private void Form1_Load(object sender, EventArgs e)
        {
            string dbPath = Application.StartupPath + @"\Data.db";
            using (SQLiteConnection con = new SQLiteConnection("Data Source=" + dbPath))
            {
                //空のテーブルを作ります。
                //この時点では、DataGridViewと紐づいていません。
                DataTable dataTable = new DataTable();

                //DataTableに読み込むデータをSQLで指定します。
                //今回はDataTableを指定していないので、SELECTで表示する列名が
                //のちのち紐づけを行った際のDataGridViewの列名になります。
                SQLiteDataAdapter adapter = new SQLiteDataAdapter("SELECT * FROM sample;", con);
                adapter.Fill(dataTable);

                //データテーブルをDataGridViewに紐づけます。
                this.dataGridView1.DataSource = dataTable;
            }
        }






■表示をクリアする
DataTableとDataGridViewをbindingしていると this.DataGridView1.Rows.Clear() ではクリアできません。
DataGridViewはあくまでもDataTableの内容をただ表示しているだけなので、DataTable自身をクリアしないといけません。



using System;
using System.Data;
using System.Data.SQLite;
using System.Windows.Forms;

namespace WindowsFormsApplication2
{
    public partial class Form1 : Form
    {
        private DataTable datatable { get; set; }

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            string dbPath = Application.StartupPath + @"\Data.db";
            using (SQLiteConnection con = new SQLiteConnection("Data Source=" + dbPath))
            {
                con.Open();
                
                //空のテーブルを作ります。
                //この時点では、DataGridViewと紐づいていません。
                this.datatable = new DataTable();

                //DataTableに読み込むデータをSQLで指定します。
                //今回はDataTableを指定していないので、SELECTで表示する列名が
                //のちのち紐づけを行った際のDataGridViewの列名になります。
                SQLiteDataAdapter adapter = new SQLiteDataAdapter("SELECT * FROM sample;", con);
                adapter.Fill(this.datatable);

                //データテーブルをDataGridViewに紐づけます。
                this.dataGridView1.DataSource = this.datatable;
            }
        }

        private void BtnClear_Click(object sender, EventArgs e)
        {
            this.datatable.Clear();
        }
    }
}


表示を消したなら、再表示したいとこですね。
Readボタンを追加。



using System;
using System.Data;
using System.Data.SQLite;
using System.Windows.Forms;

namespace WindowsFormsApplication2
{
    public partial class Form1 : Form
    {
        private DataTable datatable { get; set; }
        private SQLiteConnection con { get; set; }
        private SQLiteDataAdapter adapter { get; set; }

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            string dbPath = Application.StartupPath + @"\Data.db";
            this.con = new SQLiteConnection("Data Source=" + dbPath);
            this.con.Open();
            
            //空のテーブルを作ります。
            //この時点では、DataGridViewと紐づいていません。
            this.datatable = new DataTable();

            //データテーブルをDataGridViewに紐づけます。
            this.dataGridView1.DataSource = this.datatable;

            //データを読み込みます
            this.DataRead();
        }

        private void BtnClear_Click(object sender, EventArgs e)
        {
            this.datatable.Clear();
        }

        private void BtnRead_Click(object sender, EventArgs e)
        {
            this.DataRead();
        }

        private void DataRead()
        {
            //DataGridViewにどんどん追加されるので、一度初期化してから追加する
            this.datatable.Clear();
            adapter = new SQLiteDataAdapter("SELECT * FROM sample;", con);
            adapter.Fill(this.datatable);
        }
    }
}


最後にDataGridViewの内容を変更した結果をDBに反映します。



using System;
using System.Data;
using System.Data.SQLite;
using System.Windows.Forms;

namespace WindowsFormsApplication2
{
    public partial class Form1 : Form
    {
        private DataTable datatable { get; set; }
        private SQLiteConnection con { get; set; }
        private SQLiteDataAdapter adapter { get; set; }

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            string dbPath = Application.StartupPath + @"\Data.db";
            this.con = new SQLiteConnection("Data Source=" + dbPath);
            this.con.Open();
            
            //空のテーブルを作ります。
            //この時点では、DataGridViewと紐づいていません。
            this.datatable = new DataTable();

            //データテーブルをDataGridViewに紐づけます。
            this.dataGridView1.DataSource = this.datatable;

            //データを読み込みます
            this.DataRead();
        }

        private void BtnClear_Click(object sender, EventArgs e)
        {
            this.datatable.Clear();
        }

        private void BtnRead_Click(object sender, EventArgs e)
        {
            this.DataRead();
        }

        private void DataRead()
        {
            //DataGridViewにどんどん追加されるので、一度初期化してから追加する
            this.datatable.Clear();
            adapter = new SQLiteDataAdapter("SELECT * FROM sample;", con);
            adapter.Fill(this.datatable);
        }

        private void BtnUpdate_Click(object sender, EventArgs e)
        {
            try
            {
                using(SQLiteTransaction trans = this.con.BeginTransaction())
                {
                    SQLiteCommandBuilder builder = new SQLiteCommandBuilder(this.adapter);
                    builder.SetAllValues = false;
                    builder.ConflictOption = ConflictOption.OverwriteChanges;

                    this.adapter.Update(this.datatable);
                    trans.Commit();
                }

                MessageBox.Show("Update完了");
            }
            catch (Exception ex) 
            {
                MessageBox.Show(ex.Message);
            }
        }
    }
}

SQLiteCommandBuilderがDataTableの列名や主キーなどの情報と
変更内容から適宜、SQLを組み立てて実行してくれます。

ちなみに、下記のようにBtnUpdate_Clickを書き換えると・・・

private void BtnUpdate_Click(object sender, EventArgs e)
        {
            try
            {
                using(SQLiteTransaction trans = this.con.BeginTransaction())
                {
                    SQLiteCommandBuilder builder = new SQLiteCommandBuilder(this.adapter);
                    builder.SetAllValues = false;
                    builder.ConflictOption = ConflictOption.OverwriteChanges;

                    MessageBox.Show(builder.GetUpdateCommand().CommandText);
                    MessageBox.Show(builder.GetInsertCommand().CommandText);
                    MessageBox.Show(builder.GetDeleteCommand().CommandText);

                    int ret = this.adapter.Update(this.datatable);
                    trans.Commit();

                    string message = string.Format("Update完了\n{0}件変更", ret);
                    MessageBox.Show(message);
                }
            }
            catch (Exception ex) 
            {
                MessageBox.Show(ex.Message);
            }
        }







SQLiteCommandBuilderは、自動的に状況に応じてSQLを発行してくれるのでとても便利ではあるのですが
当然ながら万能なものではないので、あらゆるものがUpdateしたりDeleteしたりできるわけではないです。

そのため、主キーを利用したものに限られます。

あと、this.adapter.Update(this.datatable)で変更のレコード数を返します。
これは、Readするときに使っている
adapter.Fill(this.datatable);
も戻り値としてintの変数で受けるとSelectした行数が取得できます。

0 件のコメント:

コメントを投稿