System.Data.SQLiteはSQLiteと接続するためのクラスライブラリではなく、SQLiteをC#で書きなおしてSQLiteそのものをクラスライブラリ化したものです。よって、プログラムの実行には、System.Data.SQLite.dllがあれば基本的に動作します。
System.Data.SQLiteを使うためのサンプルプログラムを作成し、.NET Framewoekが導入済みでSQLiteは導入していない環境にファイルコピーして動作するかを確認してみましょう。
サンプル用プロジェクトの作成
.NET Framework 2.0のWIndowsアプリケショーンプロジェクトを新規作成します。
参照設定で、System.Data.SQLite.dllを選択します。
また、配布の事を考えてコンポーネントをローカルにコピーするように設定します。
さらに「SQLite3を使ってみた」で作成したtest.dbファイルもプロジェクトに加えて、[出力ディレクトリにコピー]プロパティを「新しいときはコピーする」に設定します。
これで、プロジェクトの準備はできました。
余談ですが、.NET Frameworkのクラスライブラリの命名から考えると、System.Data.SQLiteではなく、SQLite.Dataのような名前が適切だと思いました(ODP.NETは、Oracle.DataAccess)。
Visual Basic 2008でプログラミングする
System.Data.SQLiteは、ADO.NET 2.0相当のデータアクセスメソッドをもっているので、VB2005でもVB2008でも同じようにプログラミングできます。そこで次のような画面をもつサンプルプログラムを作成して、接続、データ取得、データ更新のコードを確認してみましょう。
SQLiteのファイルと接続する
Imports System.Data.SQLite
Public Class SampSQLite
Private Ds As New DataSet
Private ConnectionString As String = "data source={0}"
Private Sub SampSQLite_Shown(ByVal sender As Object, _
ByVal e As System.EventArgs) _
Handles Me.Shown
ConnectionString = String.Format(ConnectionString, _
System.IO.Path.Combine(My.Application.Info.DirectoryPath, _
"test.db"))
End Sub
Private Sub Connect_Button_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles Connect_Button.Click
Cursor.Current = Cursors.WaitCursor
Using _cn As New SQLiteConnection
Try
_cn.ConnectionString = ConnectionString
_cn.Open()
MessageBox.Show("Open成功", Me.Text)
Catch ex As Exception
MessageBox.Show(ex.Message, Me.Text)
Finally
Try
_cn.Close()
Catch ex As Exception
End Try
Cursor.Current = Cursors.Default
End Try
End Using
End Sub
End Class
System.Data.SQLiteはADO.NET 2.0互換のメンバ(プロパティ、メソッド、イベントなど)を持っています。
例えば、接続ならばSystem.Data.SQLite.SQLiteConnectionクラスのConnectionStringプロパティに接続文字列(SQLiteファイルの絶対パスファイル名)を入れてからOpenメソッドを実行します。クラスこそ独自ですが、ConnectionStringプロパティやOpenメソッドはSQL ServerやOracle Databaseを使うときと同じです。
SQLiteのテーブルから値を取得する
ADO.NETを使ってテーブルから値を取得する方法には、DataReaderを使う方法とDataAdapterを使う方法があります。ここでは、DataAdapterを使う方法をご紹介します。
Public Class SampSQLite
Private Ds As New DataSet
Private ConnectionString As String = "data source={0}"
Private Sub SampSQLite_Shown(ByVal sender As Object, _
ByVal e As System.EventArgs) _
Handles Me.Shown
ConnectionString = String.Format(ConnectionString, _
System.IO.Path.Combine(My.Application.Info.DirectoryPath, _
"test.db"))
End Sub
Private Sub GetRecords_Button_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles GetRecords_Button.Click
Cursor.Current = Cursors.WaitCursor
Using _cn As New SQLiteConnection
Try
_cn.ConnectionString = ConnectionString
_cn.Open()
Using _cmd As New SQLiteCommand("SELECT * FROM EMP", _cn)
Using _da As New SQLiteDataAdapter(_cmd)
_da.Fill(Ds, "EMP")
Me.Result_Grid.DataSource = Ds.Tables("EMP")
End Using
End Using
Catch ex As Exception
MessageBox.Show(ex.Message, Me.Text)
Finally
Try
_cn.Close()
Catch ex As Exception
End Try
Cursor.Current = Cursors.Default
End Try
End Using
End Sub
End Class
データを習得するためには、以下の手順を実行します。 SQLiteConnectionをOpen SQLiteCommandにSELECT文を設定 SELECT文を設定したSQLiteCommandを指定してSQLiteDataAdapterを生成 SQLiteDataAdatpterのFilllメソッドによりDataSetにレコード設定 DataSetに入ってしまえば、データの取得元は関係なくなりますので、DataGridViewのデータソースとして指定すればテーブルの内容をグリッド表示できます。
SQLiteのテーブルの値を更新する
Imports System.Data.SQLite
Public Class SampSQLite
Private Ds As New DataSet
Private ConnectionString As String = "data source={0}"
Private Sub SampSQLite_Shown(ByVal sender As Object, _
ByVal e As System.EventArgs) _
Handles Me.Shown
ConnectionString = String.Format(ConnectionString, _
System.IO.Path.Combine(My.Application.Info.DirectoryPath, _
"test.db"))
End Sub
Private Sub SetRecords_Button_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles SetRecords_Button.Click
Cursor.Current = Cursors.WaitCursor
Using _cn As New SQLiteConnection
Try
_cn.ConnectionString = ConnectionString
_cn.Open()
Using _tr As SQLiteTransaction = _cn.BeginTransaction
Try
Using _cmd As New SQLiteCommand("SELECT * FROM EMP", _cn)
_cmd.Transaction = _tr '###重要###
Using _da As New SQLiteDataAdapter(_cmd)
Using cb As New SQLiteCommandBuilder(_da)
cb.SetAllValues = False
cb.ConflictOption = ConflictOption.OverwriteChanges
_da.UpdateCommand = cb.GetUpdateCommand()
_da.InsertCommand = cb.GetInsertCommand()
_da.DeleteCommand = cb.GetDeleteCommand()
MessageBox.Show(_da.UpdateCommand.CommandText, Me.Text)
MessageBox.Show(_da.InsertCommand.CommandText, Me.Text)
MessageBox.Show(_da.DeleteCommand.CommandText, Me.Text)
_da.Update(Ds, "EMP")
MessageBox.Show("Update", Me.Text)
End Using
End Using
End Using
_tr.Commit()
Catch ex As Exception
MessageBox.Show(ex.Message, Me.Text)
_tr.Rollback()
Finally
End Try
End Using
Catch ex As Exception
MessageBox.Show(ex.Message, Me.Text)
Finally
Try
_cn.Close()
Catch ex As Exception
End Try
End Try
Cursor.Current = Cursors.Default
End Using
End Sub
End Class
画面上での変更は随時DataSetに自動反映されますので、SQLiteのデータ更新はDataSetの値を反映する処理になります。
DataSetからの反映にもSQLiteDataAdapterを使いますが、SELECT文ではなくUPDATE、INSERT、DELETEのSQL文が必要です。重要なのは、反映時にどのSQL文を使うかはSQLiteDataAdapterの内部実装になるので、必ず3つとも設定しておかないと実行時にエラーが発生する危険性があることを忘れないようにしてください。
3つのSQL文はそれぞれ記述してもいいのですが、SQLiteCommandBuilderを使って、SELECT文から自動生成するのが楽です。
SetAllValuesプロパティとConflictOptionプロパティをサンプルコードのように設定すれば次のようなSQL文を生成してくれます。
DataAdapterでの更新にはトランザクションを設定が必須
SQLiteに限らず、ADO.NETのDataAdapterでデータ更新をする場合、かならず明示的にトランザクションを開始して、Updateメソッドが成功したらCommit、失敗したらRollBackする必要があります。
なぜならば、データ更新対象が常に1つになるような画面構成ならば1SQL文の実行ですみますが、グリッド表示のように削除、追加、複数行の変更が行われる可能性がある場合、DataAdapterのUpdateメソッドの内部ではUPDATE、INSERT、DELETEのSQL文を別個に発行しているからです。
これは非常に重要な点です。忘れないようにしましょう。
配布する
今回のサンプルの場合、.NET Framework 2.0が入っている環境であれば、次の3つのファイルをコピーするだけでアプリが稼働しました。
「SampSQLite.exe」「System.Data.SQLite.dll」「test.db」
以上のように、SQLiteを使った.NETアプリはADO.NETの知識があれば簡単につくれますし配布も簡単にできますので、XMLファイルでは心もとない、かといって本格的なRDBMSを入れるほどではないようなときに活用して頂けたらと思います。