C#でSQLiteを利用する(追記編)

追記というか、言い訳編に近い。今まで書いてきたSQLiteのサンプルは、実際使う時にいろいろ不具合なことがあったりするので、そこを補足しとく。

問題点

サンプルプログラムで示している例だと、クエリを送るたびにデータベースファイルを開いたり閉じたりしている。これは、非常に効率が悪いということが判明している。

つまり、安直に誤解を恐れず言うと、大量のクエリを送りつけるときに、かなり遅いということ。

解決方法1

コンストラクタでトランザクション以外のopen()処理をやっておいて、IDisposableインターフェイスを継承してDispose()メソッドで資源の破棄を行う。

private SQLiteQuery()
{
    if ((connect = new SQLiteConnection("Data Source=" + dbFilename)) == null)
    {
        error("DBの接続に失敗しました。");
        return false;
    }
    if ((command = connect.CreateCommand()) == null)
    {
        error("SQLの実行ができません。");
        return false;
    }
    connect.Open();
}

このようにコンストラクタでデータベースファイルを開く処理を行っておく。ただし、トランザクションだけは、そういう処理をするとトランザクションの意味がなくなるから、固まって処理したいクエリの前後で明示的に行わないといけない。

class SQLiteQuery : IDisposable

このようにIDisposableを継承し、

void Dispose()
{
    command.Dispose();
    connect.Close();
}

Dispose()をこのように実装する(いろいろほかにもやり方はあるが)

ただし、この方法だと、外部から資源を使い終わった後に明示的にDispose()が呼び出されないと、いつまでたってもGCの回収待ち状態に陥る。これでは、またデータベースを利用しようと思った時に、2重に開こうとするためエラーとなる。

ガベージコレクタとは、プログラムが使用しなくなったメモリやプログラム間の隙間のメモリ領域を検出し解放する機能であるガベージコレクションを実行するためのモジュールのことである。引用

C#には、一応デストラクタという機構が用意されているが、これもGCの関係上、いつ実行されるかわかったものじゃないのでうまく活用できる気はしない。いったいどうしたものか、他に解決方法があればよろしく。

コメントを残す

メールアドレスが公開されることはありません。