ブログ ひまつぶし

バイクとシモネタが好きなへっぽこプログラマのおバカなブログ。

C#.NETで、SQLite

2011-06-17 23:22:04 | 言語・DB・開発その他
CentOSがわかんなくてねぇ。
会社の詳しい人に聞けばいいやなんて思ってたら、「え?俺?Ubuntu入れたよ。ぐぐればいいじゃん」だって。

CentOSでWebサーバを構築しようとして、わけわかんなくて。
ゴルゴ13の、デューク東郷とエバのセッ●スシーンを読んで現実逃避していた。
「海へ向かうエバ」という話で、1974年2月の作品。
なんと、私が生まれる前の話ではないか!!
もしかしたら私はエバの生まれ変わりで・・・。

まぁ、妄想はこれくらいにして。

軽量のデータベース「SQLite」について知りたいことがあったので、色々試してみました。


SQLite - Wikipedia
テビバイト - Wikipedia

SQLiteはMySQLやPostgreSQLと同じデータベース管理システムであるが、サーバとしてではなくアプリケーションに組み込んで利用される軽量のデータベースである。 一般的なRDBMSに比べて大規模な仕事には不向きだが、中小規模ならば速度に遜色はない。 また、APIは単純にライブラリを呼び出すだけであり、データの保存に単一のファイルのみを使用することが特徴である。
データベースファイルは最大128TiB(テビバイト)


面白いね、テビバイトだって。
TB(テラバイト)とTiB(テビバイト)どちらも2の40乗バイトを表すそうなんですけど、TBは本来10の12乗を表すらしく、混同しないようにTiBという単位というか接頭辞を作ったそうです。
どちらにしろテラバイトと同じようです。
128TBというと新聞1日分が640KBとして、214748364.8日分、約58万年分?

いや、計算間違ってたらごめんなさいだけど。
すげー!!

というわけで、そんなライブラリとデータファイルだけで使えるデータベースということで、他のデータベースのようにインストールする必要もないし、裏でリソース食いまくるわけでもないし。
私の頭の中ではMDB(Microsoft Accessのデータベースのファイル形式。拡張子は「.mdb」)と同じような物かな(違うと指摘されるかもしれないけど)と思うんだけど。

そんなわけで、SQLite。
ほとんどの方がVB.NETで使っているので、私はC#で使ってみようと思いました。

私は、SQLiteを.NETで使用できるライブラリ、「System.Data.SQLite.DLL(バージョン1.0.66.0)」をもう既に持っていたけど、情報を提供する上で、ライブラリのダウンロードから説明しないと、ブログの記事として面白く無いのでダウンロードから書きます。

SQLite Home Page

ここが本家のホームページです。

このホームページのメニューに「Download」があるのでクリックします。

ダウンロードページに飛ぶので、ページの下の方にスクロールして、「System.Data.SQLite.org」をクリックします。

すると、「System.Data.SQLite.org」のダウンロードページに行くので、ご希望のインストーラーをダウンロードして下さい、前バージョンと、現行のバージョン(32ビット版、64ビット版)がダウンロード出来るようです。
私は32ビット版をダウンロードしました。おかしいね。Windows7の64bitなのに。
でも、結果的にプログラム動いたからいいや。

インストーラーを起動するとなんか「C++のライブラリをインストールしたから再起動してね」とかいうメッセージが出るのが早いか、かってに再起動するのかが早いかどちらかで、なんか変なもん入れてないだろうね。とか思いながら、再起動はキャンセルした。それが正しいかと聞かれたら、正しくないんだろうけど。

再度、インスト-ラーを起動すると、インストーラーの画面が表示されてインストールが出来るようになった。


「Program Files(x86)\System.Data.SQLite」にインストールされるようです。
あとは、何も変更せずに「Next」を押しまくってインストール完了したようです。

インストーラーでインストールするのが嫌な場合、「SOURCEFORGE」からDLLだけをダウンロード出来るようです。
System.Data.SQLite.dllをダウンロード - evemeep - SourceForge.JP
SQLite-1.0.66.0-binaries.zipをダウンロード - ADO.NET 2.0 Provider


さぁ、インストールされたテストプログラムを動かしてみよう!!


バグかよ!!

駄目だろう!!ちゃんとテストしないと。配布されたサンプルプログラムが動かないなんて駄目だよ!!

・・・なーんてね。
私も、プログラマ時代、仕様通りに動かないプログラムを納品したことがあるんでね。
へっへっへ(笑)。これはねぇ、「これは仕様です」という必殺技なんですよ。
納期が短くて間に合わないときに使う必殺技なんですよ。へっへっへ(笑)。
で、別のプログラムを納品する時までにこっそり直して、お客さんのところでバレないようにすり替えたりね。
バレても「あ、本当だ。直しておきます」なんて言っちゃったりしてね。

例えばね。1月7日がシステム全体の納品日で、お客さんのところでテストが始まるのが1月10日。
間に合わなかった部分のテストが1月25日に実施されるとすると、1月22日までに間に合わなかった部分を作って、営業の人に持って行ってもらって、テストに立ち会ってるプログラマやシステムエンジニアにこっそり差し替えてもらうの。

へっへっへ(笑)・・・・。
そんな顔しないでよ。みんなやったことあるんでしょ?へっへっへ(笑)。

いや、っていうか。そんなもんを納品されたお客さんの気持ちが今わかった!!
いや、だってさ、上司の指示でやったんだもん。私は・・・・私はね。
だってあの納期ありえなくない?

「できないと思うからできないんだ!!できると思ったらできる!!」
「やる前から諦めるな!!」
とか言うプロマネを当時殴りたかった。っていうかあいつにやらせたかった。
人間が行う作業には時間がかかり、一瞬の内にできるものではなく。絶対最低これくらいの時間がかかりますよってのがあるんですよ。それなのにそれよりも短い納期を設定されるのです。

ま、そりゃね。時空を歪めたらできると思うよ。
マクー空間とか、不思議時空とか発生させたらできるでしょうね。


すみません、話が逸れましたね。
そんなわけでですね。
「System.Data.SQLite.DLL(バージョン1.0.73.0)」は、インストールされた「Program Files(x86)\System.Data.SQLite」の「bin」フォルダの中に入っています。これをプロジェクトのフォルダにコピペして持ってくるのです。
プロジェクトのフォルダというか、それを使おうとする実行ファイル(exe)と同じフォルダにいれるのです。

※「バージョン1.0.73.0」はこの他に「SQLite.Interop.dll」が「System.Data.SQLite.DLL」と同じフォルダにないとエラーになる。

そして「System.Data.SQLite.DLL」を参照設定して、使えるようにします。
※「SQLite.Interop.dll」は参照設定できないのでそのまま同じフォルダに入れていればいい。


さぁ、プログラムを組んで動かしてみよう!!

いきなり出鼻をくじかれた・・・。

よくわかんないけど、エラーメッセージで検索したらこのブログが出てきて。解決?
解決したんだけど。
[C#] 混合モード アセンブリはバージョン ‘v2.0.50727′ のランタイムに対して作成されており、追加の構成情報がないと 4.0 ランタイムでは読み込めません。


さて、プログラムは
[DB用意ボタンが押されたら]
1.データベースに表(テーブル)を作り
2.データを登録

[データ読み込みボタンが押されたら]
1.データベースからデータを読み込んで
2.画面の表に表示

[表示をクリアボタンが押されたら]
1.画面の表をクリアします

します。

データベースのファイル名は「test.db」としていますが、ファイル名、拡張子は何でもいいようです。
「test.dat」でも同じ動作をしました。



バージョン1.0.73.0の場合「SQLite.Interop.dll」が「System.Data.SQLite.DLL」と同じフォルダ(通常実行ファイルと同じフォルダ)に存在しない場合は、実行時エラーになります。



最後に、データベースファイルが存在しない場合、データベースの接続を開くと
(ソース内では「conn.Open(); // DBに接続」の時点で)
データベースのファイルが作られます。
これを確かめたくて、プログラムを作りました。

ちなみにプログラムは、突っ込まれないように頑張れば頑張るほどカオスになってきたので、ここらへんで勘弁して下さい。

へっへっへ(笑)。仕様なんですよ。




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

using System.IO;
using System.Data.SQLite;

namespace SQLiteTest
{
    public partial class frmMain : Form
    {
        // 定数・変数宣言
        const string DATABASE_NAME = "test.db"; // データベースファイル名
        /*
         * ↑これ定数にしとかないと、コメントで突っ込まれると思った。
         * 3箇所あるもんね。
         */
        string gDataBaseFilePath = 
            Path.Combine(Path.GetDirectoryName(Application.ExecutablePath), DATABASE_NAME);
        string gDataSource = "Data Source="
            + Path.Combine(Path.GetDirectoryName(Application.ExecutablePath), DATABASE_NAME);

        public frmMain()
        {
            InitializeComponent();
        }

        /// <summary>
        /// DB用意ボタン押下時の処理
        /// </summary>
        private void btnDBReady_Click(object sender, EventArgs e)
        {
            // 変数の宣言
            string sql;             // SQL文
            SQLiteCommand command;  // SQLコマンド

            // データベースファイルが存在する場合削除する
            /*
             * いや、普通はテーブルの存在を確認して、存在したらテーブル削除してから
             * テーブルを作りなおせばいいだけの話なんですけどね。
             * そうするのが普通なんでしょうけど。
             * なんか面倒くさかったのでこうした。
             * ヒャッホ━━━━(゜∀゜)━━━━ッ!!
             */
            if (File.Exists(gDataBaseFilePath))
            {
                File.Delete(gDataBaseFilePath);
            }

            // DBの接続を開く
            using (SQLiteConnection conn = new SQLiteConnection(gDataSource))
            {
                try
                {
                    conn.Open();    // DBに接続

                    // テーブルの作成
                    sql =
                        "create table item (" +
                        " id integer," +
                        " item text, " +
                        " tanka integer," +
                        " zaiko integer" +
                        " )";
                    command = new SQLiteCommand(sql, conn);
                    command.ExecuteNonQuery();
                    MessageBox.Show("テーブルを作成しました");

                    // データの挿入
                    sql = "insert into item values (1, 'りんご', 100, 45)";
                    command = new SQLiteCommand(sql, conn);
                    command.ExecuteNonQuery();
                    sql = "insert into item values (2, 'みかん', 120, 35)";
                    command = new SQLiteCommand(sql, conn);
                    command.ExecuteNonQuery();
                    MessageBox.Show("データの挿入が終わりました");
                }
                catch (Exception ex)
                {
                    // エラーメッセージ表示
                    MessageBox.Show(ex.Message);
                }
                finally
                {
                    // DB接続を閉じる
                    conn.Close();
                }
            }
        }

        /// <summary>
        /// データ読み込みボタン押下時の処理
        /// </summary>
        private void btnReadData_Click(object sender, EventArgs e)
        {
            // 変数の宣言
            SQLiteCommand command;  // コマンド
            string sql;             // SQL文

            using (SQLiteConnection conn = new SQLiteConnection(gDataSource))
            {
                try
                {
                    conn.Open();

                    // DBからデータを取得する
                    sql = "select id, item, tanka, zaiko from item order by id asc";
                    command = new SQLiteCommand(sql, conn);
                    SQLiteDataReader reader = command.ExecuteReader();

                    // 取得したデータをデータグリッドビュー(表)に表示する。
                    while (reader.Read())   // データがあるだけ繰り返す
                    {
                        dgvItem.Rows.Add(
                            reader.GetInt32(0),     // id
                            reader.GetString(1),    // 商品名
                            reader.GetInt32(2),     // 単価
                            reader.GetInt32(3));    // 個数(在庫)
                    }
                }
                catch (Exception ex)
                {
                    // エラーメッセージ表示
                    MessageBox.Show(ex.Message);
                }
                finally
                {
                    // DB接続を閉じる
                    conn.Close();
                }
            }
        }

        /// <summary>
        /// データグリッドの表示をクリアする
        /// </summary>
        private void btnClear_Click(object sender, EventArgs e)
        {
            // データグリッドビュー(表)をクリアする
            dgvItem.Rows.Clear();
        }
    }
}



最新の画像もっと見る

コメントを投稿

ブログ作成者から承認されるまでコメントは反映されません。