VB.NETからSQLiteを使う方法:基本を徹底解説

はい、承知いたしました。VB.NETからSQLiteを使用するための基本を徹底的に解説する、約5000語の詳細な記事を記述します。


VB.NETからSQLiteを使う方法:基本を徹底解説

はじめに

デスクトップアプリケーション開発において、データの永続化は不可欠な要素です。ユーザー設定の保存、小規模なデータ管理、オフラインでのデータ操作など、様々なシーンでデータベースが必要になります。しかし、大規模なデータベースサーバー(SQL Server、Oracle、MySQLなど)はセットアップや管理が複雑で、アプリケーションの配布も煩雑になりがちです。

ここで、SQLiteが非常に便利な選択肢として登場します。SQLiteは、サーバープロセスを持たず、データベース全体が単一のファイルとして格納される組み込み型データベースエンジンです。軽量で、セットアップが不要、配布が容易という特徴から、VB.NETのようなデスクトップアプリケーションやモバイルアプリケーション、組み込みシステムなどで広く利用されています。

本記事では、VB.NETアプリケーションからSQLiteデータベースを操作するための基本的な方法を、コード例を交えながら徹底的に解説します。具体的には、以下の内容を扱います。

  1. SQLiteの基本的な特徴とVB.NETで使うメリット
  2. プロジェクトへのSystem.Data.SQLiteライブラリの追加方法
  3. データベースファイルへの接続と開閉
  4. テーブルの作成
  5. データの挿入 (INSERT)
  6. データの読み込み (SELECT) – 様々な方法
  7. データの更新 (UPDATE)
  8. データの削除 (DELETE)
  9. パラメータを使った安全なデータ操作
  10. トランザクション処理によるデータの整合性維持
  11. エラーハンドリングとリソース管理
  12. ベストプラクティス

この記事を読むことで、VB.NETアプリケーションにSQLiteデータベースを組み込み、基本的なデータ操作を行うための知識とスキルを習得できるでしょう。

1. SQLiteの基本的な特徴とVB.NETで使うメリット

SQLiteとは?

SQLiteは、サーバーレス、自己完結型、設定不要、トランザクション対応のSQLデータベースエンジンです。最も広く展開されているデータベースエンジンの1つであり、その特徴は以下の通りです。

  • サーバーレス: データベースサーバープロセスが不要です。アプリケーションが必要に応じてデータベースファイルを直接操作します。
  • 自己完結型: 外部依存がほとんどなく、単一のライブラリファイル(または数個のファイル)で動作します。
  • 設定不要: インストールや設定プロセスが不要です。ライブラリを組み込み、データベースファイルを指定するだけで使えます。
  • トランザクション対応: ACID特性(原子性、一貫性、独立性、永続性)を備えたトランザクションを完全にサポートしています。
  • 単一ファイル: データベース全体が通常、1つの標準的なディスクファイルに格納されます。
  • 軽量: ライブラリのサイズが小さく、メモリ使用量も少ないです。
  • オープンソース: 商用・非商用を問わず、自由に利用・配布できます。

VB.NETでSQLiteを使うメリット

VB.NETで開発する際にSQLiteを選択することには、いくつかの大きなメリットがあります。

  • 配布の容易さ: データベースが単一ファイルであるため、アプリケーションと一緒にデータベースファイルをコピーするだけで配布が完了します。クライアント側に別途データベースサーバーのインストールや設定を求める必要がありません。これは、特に配布対象が多い場合や、ITの専門家がいない環境に配布する場合に非常に有利です。
  • 開発・テストの簡便さ: 開発環境でも特別なセットアップは不要です。ファイルベースなので、データベースのバックアップやコピーも簡単です。
  • リソース消費の少なさ: 軽量であるため、特にリソースが限られている環境や、多数のインスタンスが同時に実行される場合に適しています。
  • オフライン対応: ネットワーク接続がない環境でも、ローカルのデータベースファイルにアクセスしてデータを操作できます。
  • コスト: 商用ライセンスが不要なため、開発コストを抑えることができます。

ただし、SQLiteは同時書き込みには強くありません(複数のプロセスが同時に書き込もうとするとロックが発生しやすい)。また、非常に大規模なデータセットや、高い同時実行性が求められるエンタープライズレベルのサーバーアプリケーションには向かない場合があります。しかし、一般的なデスクトップアプリケーションのデータ管理においては、これらのデメリットはほとんど問題になりません。

2. プロジェクトへのSystem.Data.SQLiteライブラリの追加方法

VB.NETからSQLiteを操作するためには、専用のデータプロバイダが必要です。ADO.NETの標準インターフェース (System.Data.IDbConnection, System.Data.IDbCommand など) を実装したライブラリを使用します。最も一般的で推奨されるライブラリは、System.Data.SQLiteです。これはNuGetパッケージとして提供されており、プロジェクトに簡単に追加できます。

NuGetパッケージマネージャーを使用してSystem.Data.SQLiteを追加する手順は以下の通りです。

  1. Visual Studioで対象のVB.NETプロジェクトを開きます。
  2. ソリューションエクスプローラーでプロジェクトを右クリックし、「NuGetパッケージの管理…」を選択します。
  3. 「参照」タブを選択します。
  4. 検索ボックスに「System.Data.SQLite」と入力します。
  5. 検索結果から「System.Data.SQLite」または「System.Data.SQLite.Core」を選択します。(通常は.Coreが付いている方で十分です。必要に応じて.Linq, .EF6 など、他のパッケージもインストールできますが、基本操作には.CoreがあればOKです)
  6. 選択したパッケージの詳細が表示されるので、プロジェクトを選択し、「インストール」ボタンをクリックします。
  7. ライセンス同意画面が表示されたら、内容を確認して同意します。
  8. インストールが完了すると、プロジェクトの参照にSystem.Data.SQLiteが追加され、binフォルダに必要なDLLファイルがコピーされます。

これで、プロジェクト内でSystem.Data.SQLiteの名前空間(System.Data.SQLite)を使用できるようになり、SQLiteデータベースへの接続や操作を行う準備が整いました。

3. データベースファイルへの接続と開閉

SQLiteデータベースを操作するには、まずデータベースファイルへの接続を確立する必要があります。ADO.NETでは、System.Data.SQLite.SQLiteConnection クラスを使用します。

データベースファイルは、接続文字列で指定します。最も基本的な接続文字列は以下の形式です。

Data Source=データベースファイルのパス;Version=3;

  • Data Source: データベースファイルのパスを指定します。相対パスでも絶対パスでも構いません。アプリケーションの実行ファイルと同じディレクトリに置く場合は、ファイル名だけを指定することもできます (Data Source=MyDatabase.db;)。
  • Version=3: SQLiteのバージョンを指定します。現在のSQLiteではバージョン3が標準です。
  • 他にも様々なオプションがありますが、基本的にはこの形式で十分です。

データベースファイルが存在しない場合は、接続時に自動的に作成されます。

接続を確立し、操作が完了したら、必ず接続を閉じる必要があります。これはリソースを解放し、ファイルのロックを解除するために重要です。Close() メソッドを呼び出すか、より推奨される方法として Using ステートメントを使用します。

接続の確立と閉鎖 (Using ステートメントを使用)

“`vb.net
Imports System.Data.SQLite ‘ この行をコードファイルの先頭に追加

Public Class DatabaseHelper

Private dbFilePath As String = "Data Source=.\MyAppData.db;Version=3;" ' データベースファイルのパス (実行ファイルと同じディレクトリ)

' データベース接続を開く関数 (Usingステートメントと組み合わせるためのヘルパー)
Private Function OpenConnection() As SQLiteConnection
    Dim connection As New SQLiteConnection(dbFilePath)
    connection.Open() ' 接続を開く
    Return connection
End Function

' --- データベース操作の例 (後述) ---

End Class
“`

OpenConnection 関数は、単に SQLiteConnection オブジェクトを作成し、接続を開いて返しているだけです。この関数自体を直接呼ぶことはあまりなく、通常は Using ステートメントの中で以下のように使用します。

“`vb.net
Imports System.Data.SQLite

Public Class DataManager

Private ReadOnly ConnectionString As String = "Data Source=.\AppData\UserData.db;Version=3;" ' アプリケーションデータフォルダなどに配置する場合

Public Sub PerformDatabaseOperation()
    ' Using ステートメントを使用することで、接続が自動的に閉じられ、リソースが解放されます。
    ' 例外が発生した場合でも確実に実行されます。
    Using connection As New SQLiteConnection(ConnectionString)
        Try
            connection.Open()

            ' --- ここでデータベース操作 (CREATE TABLE, INSERT, SELECT, UPDATE, DELETEなど) を行います ---
            Console.WriteLine("データベース接続に成功しました。")
            ' 例: テーブルを作成するコード (後述)

        Catch ex As Exception
            ' エラー処理
            Console.WriteLine($"データベースエラーが発生しました: {ex.Message}")
        Finally
            ' Using ステートメントを使っているので、connection.Close() は明示的に書かなくてもOKですが、
            ' 理解のためにコメントとして残します。
            ' connection.Close() ' Usingステートメントが自動的に呼び出します。
        End Try
    End Using ' ここでconnection.Dispose()が呼ばれ、Close()が実行されます。

    Console.WriteLine("データベース接続を閉じました。")
End Sub

End Class
“`

Using ステートメントは、IDisposable インターフェースを実装したオブジェクト(SQLiteConnection, SQLiteCommand, SQLiteDataReader などが該当します)の Dispose() メソッドを、ブロックの終了時に自動的に呼び出す便利な構文です。Dispose() メソッドは通常、リソースの解放(データベース接続の切断、ファイルのクローズなど)を行います。これにより、接続を閉じ忘れるミスを防ぎ、リソースリークを防止できます。データベース操作においては、Using ステートメントを使うことが強く推奨されます。

4. テーブルの作成

データベースファイルにデータを格納するためには、まずテーブルを作成する必要があります。テーブルの構造は、列(カラム)の名前、データ型、制約(主キー、NOT NULLなど)によって定義されます。

テーブルを作成するには、SQLの CREATE TABLE 文を使用します。このSQL文を SQLiteCommand オブジェクトに設定し、ExecuteNonQuery() メソッドを実行します。ExecuteNonQuery() メソッドは、SELECT以外のSQL文(INSERT, UPDATE, DELETE, CREATE, DROPなど)を実行し、影響を受けた行数を返します(CREATE TABLEの場合は通常-1)。

SQLiteの主なデータ型は以下の通りです。

  • NULL: NULL値。
  • INTEGER: 符号付き整数。格納する値の大きさに応じて1, 2, 3, 4, 6, または8バイトで格納されます。主キーによく使われます。
  • REAL: 浮動小数点数。8バイトIEEE浮動小数点数として格納されます。
  • TEXT: 文字列。UTF-8, UTF-16BE, UTF-16LEのいずれかのエンコーディングで格納されます。長さの指定は不要です。
  • BLOB: バイナリデータ(画像、ファイルなど)。入力されたデータと完全に同じ形で格納されます。

SQLiteは「動的な型付け」の側面も持っており、どんな値でもカラムに格納できますが、指定した型は優先される格納クラス(ストレージクラス)を示します。基本的には、他のデータベースと同様に適切な型を指定するのが良いでしょう。

テーブル作成のコード例

ユーザー情報を格納する Users テーブルを作成する例を考えます。

“`vb.net
Imports System.Data.SQLite

Public Class DataManager

Private ReadOnly ConnectionString As String = "Data Source=.\AppData\UserData.db;Version=3;"

Public Sub CreateUsersTable()
    ' テーブル作成のSQL文
    ' IF NOT EXISTS を使うと、テーブルが既に存在する場合にエラーにならずスキップされます。
    Dim createTableSql As String = "
        CREATE TABLE IF NOT EXISTS Users (
            UserID INTEGER PRIMARY KEY AUTOINCREMENT,
            UserName TEXT NOT NULL UNIQUE,
            Email TEXT UNIQUE,
            RegistrationDate TEXT
        );
    "

    ' Usingステートメントで接続とコマンドを管理
    Using connection As New SQLiteConnection(ConnectionString)
        Using command As New SQLiteCommand(createTableSql, connection)
            Try
                connection.Open()
                ' ExecuteNonQueryは、SELECT以外のSQLを実行します
                command.ExecuteNonQuery()
                Console.WriteLine("テーブル 'Users' が作成または既に存在します。")

            Catch ex As Exception
                Console.WriteLine($"テーブル作成エラー: {ex.Message}")
            End Try
        End Using ' CommandがDisposeされる
    End Using ' ConnectionがDisposeされる (閉じられる)
End Sub

' ... 他のメソッド (INSERT, SELECTなど) ...

End Class
“`

この例では、以下の構造を持つ Users テーブルを作成します。

  • UserID: INTEGER型で、主キー (PRIMARY KEY) かつ自動採番 (AUTOINCREMENT) です。新しい行が挿入されるたびにユニークな整数値が自動的に割り振られます。
  • UserName: TEXT型で、NULLを許容せず (NOT NULL)、値が重複しない (UNIQUE) 制約があります。
  • Email: TEXT型で、値が重複しない (UNIQUE) 制約があります(NULLは許容されます)。
  • RegistrationDate: TEXT型です。日付や時刻はSQLiteでは専用の型がありませんが、TEXT, REAL, INTEGERのいずれかで格納するのが一般的です。TEXT形式(例: ‘YYYY-MM-DD HH:MM:SS’)が可読性が高く推奨されます。

Using command As New SQLiteCommand(createTableSql, connection) のように、SQLiteCommandUsing ステートメントで囲むのがベストプラクティスです。これにより、コマンドに関連付けられたリソースも適切に解放されます。

この CreateUsersTable メソッドを、アプリケーションの起動時などに一度だけ呼び出すことで、必要なテーブルがデータベースに準備されます。

5. データの挿入 (INSERT)

テーブルを作成したら、いよいよデータを挿入します。データの挿入には、SQLの INSERT INTO 文を使用します。

INSERT INTO テーブル名 (列1, 列2, ...) VALUES (値1, 値2, ...);

または、全ての列に値を指定する場合は、列リストを省略できます。

INSERT INTO テーブル名 VALUES (値1, 値2, ...);

ただし、列リストを省略する場合は、テーブル定義での列の順番と完全に一致させる必要があり、テーブル定義が変更された場合にコードも修正が必要になるため、列リストを明示する方が安全です。

値をSQL文に直接埋め込むことも可能ですが、絶対に推奨されません。特にユーザーからの入力値などを直接埋め込むと、SQLインジェクションの脆弱性が生まれるだけでなく、値に引用符や特殊文字が含まれている場合にSQLの構文エラーが発生しやすくなります。代わりに、パラメータを使用する必要があります。パラメータを使う方法については、後述の「パラメータを使った安全なデータ操作」で詳しく説明しますが、ここではパラメータを使った挿入の例を示します。

パラメータを使ったデータ挿入のコード例

先ほど作成した Users テーブルに新しいユーザーを挿入する例です。

“`vb.net
Imports System.Data.SQLite
Imports System.IO ‘ Path.Combineなどを使うため

Public Class DataManager

Private ReadOnly ConnectionString As String = $"Data Source={Path.Combine(Application.StartupPath, "AppData", "UserData.db")};Version=3;"

' AppDataフォルダを作成するヘルパーメソッド (必要に応じて)
Private Sub EnsureAppDataFolderExists()
    Dim appDataPath As String = Path.Combine(Application.StartupPath, "AppData")
    If Not Directory.Exists(appDataPath) Then
        Directory.CreateDirectory(appDataPath)
    End If
End Sub

Public Sub AddNewUser(userName As String, email As String)
    EnsureAppDataFolderExists() ' フォルダが存在することを確認

    ' INSERT文。値の部分にはパラメータ名(例: @UserName, @Email)を指定します。
    ' UserIDはAUTOINCREMENTなので指定不要です。RegistrationDateも今は指定しない例とします。
    Dim insertSql As String = "
        INSERT INTO Users (UserName, Email)
        VALUES (@UserName, @Email);
    "

    Using connection As New SQLiteConnection(ConnectionString)
        Using command As New SQLiteCommand(insertSql, connection)
            ' パラメータをコマンドに追加します。
            ' パラメータ名(@UserNameなど)と対応する値を指定します。
            ' AddWithValueは便利ですが、型を明示したい場合は Add(New SQLiteParameter(...)) を使います。
            ' SQLiteでは型指定は緩やかですが、AddWithValueで問題ないことが多いです。
            command.Parameters.AddWithValue("@UserName", userName)
            command.Parameters.AddWithValue("@Email", If(String.IsNullOrEmpty(email), DBNull.Value, email)) ' Emailが空の場合はDBNull.Valueを挿入

            Try
                connection.Open()
                ' ExecuteNonQueryを実行します。挿入された行数が返されます(通常1)。
                Dim rowsAffected As Integer = command.ExecuteNonQuery()
                Console.WriteLine($"{rowsAffected} 行が挿入されました。")

            Catch ex As Exception
                Console.WriteLine($"ユーザー挿入エラー: {ex.Message}")
                ' UNIQUE制約違反などの特定のSQLiteエラーを捕捉することも可能です
                If ex.Message.Contains("UNIQUE constraint failed") Then
                    Console.WriteLine("指定されたユーザー名またはメールアドレスは既に存在します。")
                End If
            End Try
        End Using
    End Using
End Sub

' ... 他のメソッド ...

End Class
“`

ConnectionStringApplication.StartupPathPath.Combine を使って生成することで、実行ファイルと同じディレクトリにある AppData フォルダ内にデータベースファイルを配置できます。これはアプリケーション固有のデータを格納する一般的な方法です。EnsureAppDataFolderExists のようなヘルパーメソッドを用意すると、フォルダが存在しない場合にも対応できます。

command.Parameters.AddWithValue("@UserName", userName) の行で、@UserName という名前のパラメータを作成し、その値として userName 変数の値を設定しています。SQL文中の @UserName は、実行時にこのパラメータの値に置き換えられます。これにより、どんな文字が含まれていても安全にSQL文の一部として扱われます。

ExecuteNonQuery() は、この挿入操作を実行します。成功すれば通常1が返され、エラーが発生すれば例外がスローされます。例外処理で、具体的なエラーメッセージをチェックすることで、UNIQUE制約違反などの詳細なエラー原因を特定することも可能です。

6. データの読み込み (SELECT)

データベースに格納されたデータを取得するには、SQLの SELECT 文を使用します。SELECT 文は非常に強力で、様々な条件でデータを抽出したり、集計したりできますが、ここでは基本的な読み込み方法に焦点を当てます。

SELECT 列1, 列2, ... FROM テーブル名 WHERE 条件;

  • 列1, 列2, ...: 取得したい列の名前を指定します。全ての列を取得する場合は * を使用します。
  • テーブル名: データを取得したいテーブルの名前を指定します。
  • WHERE 条件: データを絞り込むための条件を指定します。この部分を省略すると、テーブルの全ての行が取得されます。WHERE 句でもパラメータを使用するのが一般的です。

SELECT 文を実行するには SQLiteCommand オブジェクトを使用しますが、結果の取得には ExecuteReader() または ExecuteScalar() メソッドを使用します。

6.1. ExecuteReader() を使った行ごとの読み込み

ExecuteReader() メソッドは、クエリの結果を SQLiteDataReader オブジェクトとして返します。DataReader は、結果セットの各行に順にアクセスするためのオブジェクトです。大量のデータを扱う場合や、データを1行ずつ処理する場合に適しています。

DataReader は、結果セットの最初の行の前に位置しています。Read() メソッドを呼び出すごとに、次の行に進みます。Read() は、次の行が存在すれば True を、結果セットの終わりに達すれば False を返します。

各行から列の値を取得するには、列の名前またはインデックスを指定して DataReader のプロパティにアクセスします。結果のデータ型に応じて、GetInt32(), GetString(), GetDouble(), GetBoolean(), GetDateTime() などの型付きアクセスメソッドを使用するのが推奨されます。IsDBNull() メソッドで、値がNULLかどうかをチェックすることも重要です。

ExecuteReader() を使ったデータ読み込みのコード例

Users テーブルから全てのユーザー情報を取得してコンソールに表示する例です。

“`vb.net
Imports System.Data.SQLite
Imports System.IO
Imports System.Text ‘ StringBuilderを使うため

Public Class DataManager

Private ReadOnly ConnectionString As String = $"Data Source={Path.Combine(Application.StartupPath, "AppData", "UserData.db")};Version=3;"

Public Sub ListAllUsers()
    Dim selectSql As String = "SELECT UserID, UserName, Email, RegistrationDate FROM Users;"

    Using connection As New SQLiteConnection(ConnectionString)
        Using command As New SQLiteCommand(selectSql, connection)
            Dim reader As SQLiteDataReader = Nothing ' DataReaderを宣言

            Try
                connection.Open()
                ' ExecuteReader()でDataReaderを取得します
                reader = command.ExecuteReader()

                Console.WriteLine("--- ユーザーリスト ---")

                ' reader.Read()は、次の行があればTrueを返し、結果セットの終わりに達するとFalseを返します。
                While reader.Read()
                    ' 各行から列の値を取得します。列名またはインデックスでアクセスできます。
                    ' IsDBNull()でNULLチェックを忘れずに行います。
                    Dim userId As Integer = reader.GetInt32(reader.GetOrdinal("UserID")) ' 列名からインデックスを取得して型付きアクセス
                    Dim userName As String = reader.GetString(1) ' インデックスで型付きアクセス (0オリジン)

                    ' NULLの可能性がある列はIsDBNullでチェックしてから取得します
                    Dim email As String = If(reader.IsDBNull(reader.GetOrdinal("Email")), "N/A", reader.GetString(reader.GetOrdinal("Email")))
                    Dim regDate As String = If(reader.IsDBNull("RegistrationDate"), "N/A", reader.GetString("RegistrationDate")) ' 列名で直接アクセスも可能だが型に注意

                    Console.WriteLine($"ID: {userId}, 名前: {userName}, メール: {email}, 登録日: {regDate}")
                End While

                Console.WriteLine("------------------")

            Catch ex As Exception
                Console.WriteLine($"データ読み込みエラー: {ex.Message}")
            Finally
                ' DataReaderもIDisposableなので、Usingを使うかClose()で明示的に閉じます。
                ' Whileループの途中で例外が発生した場合に備え、Finallyブロックで閉じます。
                ' Usingステートメントで囲むことも可能ですが、この構造の場合はFinallyが良いでしょう。
                If reader IsNot Nothing AndAlso Not reader.IsClosed Then
                    reader.Close()
                End If
            End Try
        End Using ' CommandがDisposeされる
    End Using ' ConnectionがDisposeされる (閉じられる)
End Sub

' ... 他のメソッド ...

End Class
“`

この例では、reader.GetOrdinal("ColumnName") を使って列名からインデックスを取得し、そのインデックスを使って GetInt32()GetString() といった型付きアクセスメソッドで値を取得しています。列のインデックスは0から始まります。型付きアクセスメソッドを使うことで、適切なデータ型で値を取得でき、キャストの手間が省けます。

また、IsDBNull() メソッドを使って列の値がNULLかどうかを判定しています。NULLの可能性がある列(例: Email, RegistrationDate)については、値を読み取る前に必ずNULLチェックを行うべきです。NULLである場合に GetString() などを呼び出すとエラーになる可能性があります。三項演算子 If(条件, 真の場合, 偽の場合) を使うと、NULLの場合は代替の値(”N/A”など)を表示する処理を簡潔に記述できます。

SQLiteDataReader オブジェクトも IDisposable インターフェースを実装しています。上の例では Finally ブロックで明示的に reader.Close() を呼び出していますが、Using ステートメントで囲むことも可能です。ただし、DataReader の寿命は Command に依存するため、CommandUsing ブロックの中に DataReaderUsing ブロックを入れる形になります。

“`vb.net
‘ — DataReaderをUsingで囲む場合の例 —
Using connection As New SQLiteConnection(ConnectionString)
Using command As New SQLiteCommand(selectSql, connection)
Try
connection.Open()
‘ DataReaderをUsingで囲む
Using reader As SQLiteDataReader = command.ExecuteReader()
While reader.Read()
‘ … データの読み込み …
End While
End Using ‘ DataReaderがDisposeされる (Closeされる)

    Catch ex As Exception
        Console.WriteLine($"データ読み込みエラー: {ex.Message}")
    End Try
End Using ' CommandがDisposeされる

End Using ‘ ConnectionがDisposeされる
“`
この形の方がリソース管理としてはより安全で推奨されます。

6.2. WHERE句とパラメータを使った絞り込み検索

特定の条件に一致するデータだけを取得したい場合は、WHERE 句を使用します。WHERE 句の条件でも、セキュリティと安全性の観点からパラメータを使用するのが必須です。

WHERE句とパラメータを使ったデータ読み込みのコード例

特定のユーザー名を持つユーザーを検索する例です。

“`vb.net
Imports System.Data.SQLite
Imports System.IO

Public Class DataManager

Private ReadOnly ConnectionString As String = $"Data Source={Path.Combine(Application.StartupPath, "AppData", "UserData.db")};Version=3;"

Public Sub FindUserByUserName(userName As String)
    ' WHERE句で条件を指定し、値の部分にはパラメータ名(@UserName)を使用します。
    Dim selectSql As String = "
        SELECT UserID, UserName, Email, RegistrationDate
        FROM Users
        WHERE UserName = @UserName;
    "

    Using connection As New SQLiteConnection(ConnectionString)
        Using command As New SQLiteCommand(selectSql, connection)
            ' パラメータに検索条件の値を設定します。
            command.Parameters.AddWithValue("@UserName", userName)

            Dim reader As SQLiteDataReader = Nothing

            Try
                connection.Open()
                reader = command.ExecuteReader()

                Console.WriteLine($"--- ユーザー検索結果 ({userName}) ---")

                If reader.HasRows Then ' 結果行があるかチェック
                    While reader.Read()
                        Dim userId As Integer = reader.GetInt32(reader.GetOrdinal("UserID"))
                        Dim foundUserName As String = reader.GetString(reader.GetOrdinal("UserName"))
                        Dim email As String = If(reader.IsDBNull("Email"), "N/A", reader.GetString("Email"))
                        Dim regDate As String = If(reader.IsDBNull("RegistrationDate"), "N/A", reader.GetString("RegistrationDate"))

                        Console.WriteLine($"ID: {userId}, 名前: {foundUserName}, メール: {email}, 登録日: {regDate}")
                    End While
                Else
                    Console.WriteLine("指定されたユーザーは見つかりませんでした。")
                End If

                Console.WriteLine("--------------------------")

            Catch ex As Exception
                Console.WriteLine($"ユーザー検索エラー: {ex.Message}")
            Finally
                 If reader IsNot Nothing AndAlso Not reader.IsClosed Then
                    reader.Close()
                End If
            End Try
        End Using
    End Using
End Sub

' ... 他のメソッド ...

End Class
“`

この例では、WHERE UserName = @UserName という条件でデータを絞り込んでいます。@UserName パラメータに検索したいユーザー名を設定することで、安全かつ正確に検索を実行できます。reader.HasRows プロパティで、結果セットに1行以上のデータが含まれているか(つまり、検索にヒットしたか)を確認できます。

6.3. ExecuteScalar() を使った単一値の取得

クエリの結果が単一の値(例: 行数、合計値、最大値など)のみであるとわかっている場合は、ExecuteScalar() メソッドを使用するのが便利です。これは、結果セットの最初の行の最初の列の値を取得し、それを Object 型で返します。他の列や行は無視されます。

ExecuteScalar() を使った単一値取得のコード例

Users テーブルの総行数(ユーザー数)を取得する例です。

“`vb.net
Imports System.Data.SQLite
Imports System.IO

Public Class DataManager

Private ReadOnly ConnectionString As String = $"Data Source={Path.Combine(Application.StartupPath, "AppData", "UserData.db")};Version=3;"

Public Function GetUserCount() As Integer
    ' 総行数を取得するSQL COUNT(*)クエリ
    Dim countSql As String = "SELECT COUNT(*) FROM Users;"
    Dim userCount As Integer = 0

    Using connection As New SQLiteConnection(ConnectionString)
        Using command As New SQLiteCommand(countSql, connection)
            Try
                connection.Open()
                ' ExecuteScalar()を実行し、結果をObjectで取得します。
                Dim result As Object = command.ExecuteScalar()

                ' 結果がDBNullでないことを確認し、適切な型に変換します。
                If result IsNot DBNull.Value AndAlso result IsNot Nothing Then
                    userCount = Convert.ToInt32(result) ' ObjectをIntegerに変換
                End If

                Console.WriteLine($"現在のユーザー数: {userCount}")

            Catch ex As Exception
                Console.WriteLine($"ユーザー数取得エラー: {ex.Message}")
            End Try
        End Using
    End Using

    Return userCount
End Function

' ... 他のメソッド ...

End Class
“`

SELECT COUNT(*) クエリは、テーブルの総行数を返します。ExecuteScalar() はこの単一の数値を Object として返します。DBNull.ValueNothing でないことを確認してから、Convert.ToInt32() などを使って適切な数値型に変換します。

ExecuteScalar() は、ログイン処理でのユーザー認証(ユーザー名とパスワードに一致する行が存在するか確認)、IDの存在チェック、簡単な集計値の取得などに非常に便利です。

6.4. DataTable/DataSetへの読み込み (応用)

ADO.NETでは、DataAdapter クラスを使ってデータベースのデータを DataTableDataSet に一括で読み込むこともできます。これは、データをグリッドコントロール(DataGridViewなど)にバインドする場合などに便利です。

System.Data.SQLiteにも SQLiteDataAdapter クラスが提供されています。

SQLiteDataAdapter を使った DataTable への読み込み例

“`vb.net
Imports System.Data.SQLite
Imports System.IO
Imports System.Data ‘ DataTableを使うため

Public Class DataManager

Private ReadOnly ConnectionString As String = $"Data Source={Path.Combine(Application.StartupPath, "AppData", "UserData.db")};Version=3;"

Public Function GetAllUsersAsDataTable() As DataTable
    Dim selectSql As String = "SELECT UserID, UserName, Email, RegistrationDate FROM Users;"
    Dim dataTable As New DataTable() ' データを格納するDataTableを作成

    Using connection As New SQLiteConnection(ConnectionString)
        Using adapter As New SQLiteDataAdapter(selectSql, connection) ' DataAdapterを作成
            Try
                connection.Open()
                ' Fillメソッドで、DataAdapterがSELECTクエリを実行し、結果をDataTableに詰めます。
                adapter.Fill(dataTable)
                Console.WriteLine($"DataTableに {dataTable.Rows.Count} 件のユーザー情報を読み込みました。")

            Catch ex As Exception
                Console.WriteLine($"DataTableへの読み込みエラー: {ex.Message}")
                Return Nothing ' エラー時はNothingを返すなど適切に処理
            End Try
        End Using ' DataAdapterもDisposeされる
    End Using ' ConnectionがDisposeされる

    Return dataTable
End Function

' このDataTableをDataGridViewなどにバインドして表示できます
' Public Sub DisplayUsersInGrid(ByVal dgv As DataGridView)
'     Dim userData As DataTable = GetAllUsersAsDataTable()
'     If userData IsNot Nothing Then
'         dgv.DataSource = userData
'     End If
' End Sub

' ... 他のメソッド ...

End Class
“`

SQLiteDataAdapter は、内部的に SQLiteCommandSQLiteDataReader を使用してデータを取得しますが、その処理をカプセル化してくれます。Fill() メソッドを呼び出すだけで、指定した DataTableDataSet にデータが自動的に格納されます。

DataAdapter は、データの読み込みだけでなく、Update() メソッドを使って DataTable の変更(追加、更新、削除)をまとめてデータベースに反映させる機能も持っていますが、ここでは基本的な読み込みまでとします。

7. データの更新 (UPDATE)

既存のデータの値を変更するには、SQLの UPDATE 文を使用します。

UPDATE テーブル名 SET 列1 = 新しい値1, 列2 = 新しい値2, ... WHERE 条件;

  • テーブル名: 更新したいテーブルの名前を指定します。
  • SET ...: 値を変更したい列と新しい値を指定します。複数の列をカンマで区切って指定できます。
  • WHERE 条件: 更新対象の行を絞り込むための条件を指定します。 この句を省略すると、テーブルの全ての行が更新されてしまう ので、注意が必要です。

UPDATE 文の実行にも SQLiteCommandExecuteNonQuery() を使用します。値を設定する際には、INSERTと同様にパラメータを使用します。

パラメータを使ったデータ更新のコード例

特定の UserID を持つユーザーのメールアドレスを更新する例です。

“`vb.net
Imports System.Data.SQLite
Imports System.IO

Public Class DataManager

Private ReadOnly ConnectionString As String = $"Data Source={Path.Combine(Application.StartupPath, "AppData", "UserData.db")};Version=3;"

Public Sub UpdateUserEmail(userId As Integer, newEmail As String)
    ' UPDATE文。SET句とWHERE句でパラメータを使用します。
    Dim updateSql As String = "
        UPDATE Users
        SET Email = @NewEmail
        WHERE UserID = @UserID;
    "

    Using connection As New SQLiteConnection(ConnectionString)
        Using command As New SQLiteCommand(updateSql, connection)
            ' パラメータに新しい値と更新条件の値を設定します。
            command.Parameters.AddWithValue("@NewEmail", If(String.IsNullOrEmpty(newEmail), DBNull.Value, newEmail)) ' 空の場合はDBNullをセット
            command.Parameters.AddWithValue("@UserID", userId)

            Try
                connection.Open()
                ' ExecuteNonQueryを実行します。更新された行数が返されます。
                Dim rowsAffected As Integer = command.ExecuteNonQuery()

                If rowsAffected > 0 Then
                    Console.WriteLine($"ユーザーID {userId} のメールアドレスを更新しました。({rowsAffected} 行更新)")
                Else
                    Console.WriteLine($"ユーザーID {userId} は見つかりませんでした。更新は行われませんでした。")
                End If

            Catch ex As Exception
                Console.WriteLine($"ユーザー更新エラー: {ex.Message}")
            End Try
        End Using
    End Using
End Sub

' ... 他のメソッド ...

End Class
“`

WHERE UserID = @UserID のように、主キーなどのユニークな列を条件に指定することで、意図した特定の行だけを安全に更新できます。ExecuteNonQuery() の戻り値を確認することで、実際に何行が更新されたかを知ることができます。これは、更新対象の行が存在しなかった場合(戻り値が0)などに役立ちます。

8. データの削除 (DELETE)

既存のデータを削除するには、SQLの DELETE FROM 文を使用します。

DELETE FROM テーブル名 WHERE 条件;

  • テーブル名: 削除したいデータがあるテーブルの名前を指定します。
  • WHERE 条件: 削除対象の行を絞り込むための条件を指定します。 この句を省略すると、テーブルの全ての行が削除されてしまう ので、更新の場合と同様に細心の注意が必要です。

DELETE FROM 文の実行にも SQLiteCommandExecuteNonQuery() を使用します。条件を指定する際には、パラメータを使用します。

パラメータを使ったデータ削除のコード例

特定の UserID を持つユーザーを削除する例です。

“`vb.net
Imports System.Data.SQLite
Imports System.IO

Public Class DataManager

Private ReadOnly ConnectionString As String = $"Data Source={Path.Combine(Application.StartupPath, "AppData", "UserData.db")};Version=3;"

Public Sub DeleteUser(userId As Integer)
    ' DELETE FROM文。WHERE句でパラメータを使用します。
    Dim deleteSql As String = "
        DELETE FROM Users
        WHERE UserID = @UserID;
    "

    Using connection As New SQLiteConnection(ConnectionString)
        Using command As New SQLiteCommand(deleteSql, connection)
            ' パラメータに削除条件の値を設定します。
            command.Parameters.AddWithValue("@UserID", userId)

            Try
                connection.Open()
                ' ExecuteNonQueryを実行します。削除された行数が返されます。
                Dim rowsAffected As Integer = command.ExecuteNonQuery()

                If rowsAffected > 0 Then
                    Console.WriteLine($"ユーザーID {userId} を削除しました。({rowsAffected} 行削除)")
                Else
                    Console.WriteLine($"ユーザーID {userId} は見つかりませんでした。削除は行われませんでした。")
                End If

            Catch ex As Exception
                Console.WriteLine($"ユーザー削除エラー: {ex.Message}")
            End Try
        End Using
    End Using
End Sub

' ... 他のメソッド ...

End Class
“`

WHERE UserID = @UserID のように条件を指定することで、意図した特定の行だけを安全に削除できます。ExecuteNonQuery() の戻り値を確認することで、実際に何行が削除されたかを知ることができます。これは、削除対象の行が存在しなかった場合(戻り値が0)などに役立ちます。

9. パラメータを使った安全なデータ操作

ここまで見てきたように、SQLiteを含むほとんどのデータベース操作において、SQL文に値を直接埋め込むのではなく、パラメータを使用することが強く推奨されます。その理由は以下の通りです。

  1. SQLインジェクション攻撃の防止: ユーザー入力などの外部から取得した値をSQL文に直接連結すると、悪意のあるコードが埋め込まれてしまうSQLインジェクション攻撃のリスクが発生します。パラメータを使用すると、値はSQLコードとしてではなく、単なるデータとして扱われるため、この種のリスクを効果的に防ぐことができます。
  2. 構文エラーの回避: 値にシングルクォート (‘) やその他の特殊文字が含まれていても、パラメータを使用すればエスケープ処理などを気にする必要がありません。ライブラリが自動的に適切に処理してくれます。
  3. データ型の安全性: パラメータは多くの場合、値の型情報をデータベースに渡します。これにより、データベース側で適切な型変換が行われ、意図しないデータ型の不一致によるエラーを防ぐことができます。
  4. パフォーマンスの向上 (場合による): 繰り返し実行される同じ構造のクエリに対してパラメータを使用すると、データベースによってはクエリの実行プランをキャッシュして再利用し、パフォーマンスが向上することがあります。SQLiteでも多少の恩恵がある可能性があります。

パラメータの使い方は以下の手順です。

  1. SQL文の中で、値を入れたい場所に @パラメータ名 の形式でプレースホルダを記述します(SQLiteでは @ が一般的ですが、:$ も使用可能です)。
  2. SQLiteCommand オブジェクトの Parameters コレクションに、Add または AddWithValue メソッドを使ってパラメータを追加します。パラメータ名と対応する値を指定します。

パラメータ使用時の注意点

  • パラメータ名の一致: SQL文中のプレースホルダ名 (@UserName など) と、Parameters.AddWithValue で指定するパラメータ名 ("@UserName") は完全に一致させる必要があります。
  • 値の型: AddWithValue は便利ですが、System.Data.SQLiteが提供する Add(New SQLiteParameter("Name", DbType, Size, Value)) のような形式で型を明示的に指定することも可能です。SQLiteでは型指定は緩やかですが、厳密な型付けを行いたい場合や、特定のデータ型(例: BLOB)を扱う場合には役立ちます。
  • NULL値の扱い: データベースのNULL値を挿入または更新したい場合は、VB.NETの Nothing や空文字 "" ではなく、DBNull.Value をパラメータの値として指定する必要があります。

これまでのINSERT, UPDATE, SELECT (WHERE句) の例は全てパラメータを使用した形でした。常にパラメータを使用する習慣をつけましょう。

10. トランザクション処理によるデータの整合性維持

複数のデータベース操作(SQL文)を1つのまとまりとして扱い、その全てが成功するか、または全てが失敗して元に戻されるようにしたい場合があります。このような処理のまとまりをトランザクションと呼びます。

例えば、銀行の口座間送金処理では、「A口座からお金を引き出す」操作と「B口座にお金を入金する」操作の2つが必要です。もし引き出しだけ成功して入金が失敗した場合、合計金額が狂ってしまいます。トランザクションを使用すれば、この2つの操作を1つの単位として扱い、両方成功した場合のみ変更を確定(コミットCommit())し、どちらか一方でも失敗した場合は全ての変更を取り消して元の状態に戻す(ロールバックRollback())ことができます。

トランザクションは、データベースのACID特性(Atomicity: 原子性, Consistency: 一貫性, Isolation: 独立性, Durability: 永続性)を保証するために不可欠です。

VB.NETからSQLiteでトランザクションを扱う手順は以下の通りです。

  1. SQLiteConnection オブジェクトの BeginTransaction() メソッドを呼び出してトランザクションを開始します。これにより、SQLiteTransaction オブジェクトが返されます。
  2. トランザクション内で実行したい SQLiteCommand オブジェクトに、取得した SQLiteTransaction オブジェクトを設定します (command.Transaction = transaction)。
  3. 全ての操作が成功したら、SQLiteTransaction オブジェクトの Commit() メソッドを呼び出して変更を確定します。
  4. 操作中にエラーが発生した場合は、SQLiteTransaction オブジェクトの Rollback() メソッドを呼び出して、トランザクション開始時点の状態に戻します。
  5. SQLiteTransaction オブジェクトも IDisposable を実装しているため、Using ステートメントで囲むのがベストプラクティスです。

トランザクション処理のコード例

ここでは、複数のユーザーをまとめて挿入し、途中でエラーが発生したら全てキャンセルする例を考えます。

“`vb.net
Imports System.Data.SQLite
Imports System.IO

Public Class DataManager

Private ReadOnly ConnectionString As String = $"Data Source={Path.Combine(Application.StartupPath, "AppData", "UserData.db")};Version=3;"

' 複数のユーザー名をまとめて挿入するメソッド
Public Sub AddMultipleUsers(userNames As List(Of String))
    Dim insertSql As String = "INSERT INTO Users (UserName) VALUES (@UserName);"

    Using connection As New SQLiteConnection(ConnectionString)
        connection.Open() ' トランザクション開始前に接続を開く必要があります

        ' トランザクションを開始します
        ' トランザクションオブジェクトもUsingで囲みます
        Using transaction As SQLiteTransaction = connection.BeginTransaction()
            Using command As New SQLiteCommand(insertSql, connection)
                ' コマンドにトランザクションオブジェクトを設定します
                command.Transaction = transaction

                Try
                    Console.WriteLine("トランザクションを開始します...")
                    Dim totalRowsInserted As Integer = 0

                    ' リストの各ユーザー名をループして挿入
                    For Each userName As String In userNames
                        ' パラメータの値を設定
                        command.Parameters.Clear() ' パラメータをクリアする
                        command.Parameters.AddWithValue("@UserName", userName)

                        ' コマンドを実行
                        command.ExecuteNonQuery()
                        totalRowsInserted += 1
                        Console.WriteLine($"{userName} を挿入しました。")

                        ' 例: 意図的にエラーを発生させる (テスト用)
                        ' If userName = "ErrorUser" Then
                        '     Throw New Exception("テストエラーが発生しました。")
                        ' End If

                    Next

                    ' 全ての挿入が成功したらコミットします
                    transaction.Commit()
                    Console.WriteLine($"トランザクション完了: {totalRowsInserted} 件のユーザーをコミットしました。")

                Catch ex As Exception
                    ' エラーが発生したらロールバックします
                    transaction.Rollback()
                    Console.WriteLine($"トランザクション中断・ロールバック: エラーが発生しました - {ex.Message}")
                    Console.WriteLine("変更はデータベースに反映されませんでした。")

                End Try ' FinallyブロックはトランザクションのDispose()の後に実行されるため、ここでは不要
            End Using ' CommandがDisposeされる
        End Using ' TransactionがDisposeされる (CommitまたはRollbackが行われる)
    End Using ' ConnectionがDisposeされる (閉じられる)
End Sub

' ... 他のメソッド ...

End Class
“`

この例では、connection.BeginTransaction() でトランザクションを開始し、返された transaction オブジェクトを各 command に設定しています。Try ブロック内で全てのユーザーの挿入を試み、全て成功したら transaction.Commit() を呼び出します。途中で例外が発生した場合は Catch ブロックに入り、transaction.Rollback() を呼び出して、それまでに行った挿入操作を全て取り消します。

command.Parameters.Clear() は、ループ内で同じコマンドオブジェクトを再利用する際に、前回のパラメータが残らないようにクリアするために呼び出しています。

トランザクションは、複数の関連する操作の整合性を保つ上で非常に重要です。特に、データの追加・更新・削除が複数ステップに分かれるような処理では、積極的にトランザクションを利用すべきです。

11. エラーハンドリングとリソース管理

データベース操作は、様々な原因で失敗する可能性があります。例えば、

  • データベースファイルが見つからない、またはアクセス権がない
  • SQL文の構文エラー
  • 存在しないテーブルや列へのアクセス
  • UNIQUE制約やNOT NULL制約などの制約違反
  • 同時アクセスによるロックエラー
  • データ型の不一致

これらのエラーに適切に対応するためには、Try...Catch...Finally ブロックを使ったエラーハンドリングが不可欠です。

  • Try: エラーが発生する可能性のあるデータベース操作コードを記述します。
  • Catch: Try ブロック内で発生した例外(エラー)を捕捉し、エラーの種類に応じた処理を行います。Catch ex As Exception とすることで、全ての種類のエラーを捕捉できます。特定の System.Data.SQLite.SQLiteException などを捕捉して、より詳細なエラー処理を行うことも可能です。
  • Finally: Try ブロックが正常に完了した場合でも、例外が発生した場合でも、必ず実行されるコードを記述します。主にリソースの解放(データベース接続やDataReaderのクローズなど)を行います。

しかし、前述のように Using ステートメントを使用すると、Finally ブロックで明示的に Close()Dispose() を呼び出す必要がなくなります。Using ステートメントは、Finally ブロックでのリソース解放処理を自動化してくれるため、コードが簡潔になり、閉じ忘れによるリソースリークを防ぐことができます。

したがって、エラーハンドリングとリソース管理のベストプラクティスは、Try...Catch ブロックでエラーを捕捉しつつ、データベース関連オブジェクト (SQLiteConnection, SQLiteCommand, SQLiteDataReader, SQLiteTransaction) を Using ステートメントで囲む ことです。

これまでのコード例は全て、このベストプラクティスに沿った構造になっています。

“`vb.net
Using connection As New SQLiteConnection(ConnectionString)
Try
connection.Open()

    ' トランザクションが必要なら開始
    ' Using transaction As SQLiteTransaction = connection.BeginTransaction()

        Using command As New SQLiteCommand(sql, connection)
            ' command.Transaction = transaction ' トランザクションを設定

            ' パラメータを設定

            ' SELECTの場合
            ' Using reader As SQLiteDataReader = command.ExecuteReader()
            '     While reader.Read()
            '         ' データの読み込み
            '     End While
            ' End Using

            ' INSERT, UPDATE, DELETE, CREATE等の場合
            ' Dim rowsAffected As Integer = command.ExecuteNonQuery()

            ' 単一値取得の場合
            ' Dim scalarResult As Object = command.ExecuteScalar()

        End Using ' CommandがDisposeされる

    ' トランザクションが必要ならコミット
    ' transaction.Commit()

Catch ex As Exception
    ' エラー処理
    Console.WriteLine($"データベース操作エラー: {ex.Message}")
    ' トランザクションが必要ならロールバック
    ' If transaction IsNot Nothing Then transaction.Rollback()

End Try
' Usingステートメントにより、ここでは接続が自動的に閉じられる

End Using
“`

このテンプレート構造を基本とすることで、安全かつ堅牢なデータベースアクセスコードを記述できます。

12. ベストプラクティス

VB.NETからSQLiteを効果的かつ安全に利用するためのベストプラクティスをまとめます。

  • System.Data.SQLite を使用する: VB.NET (.NET Framework または .NET Core/.NET 5+) からSQLiteを扱うための標準的かつ推奨されるライブラリです。NuGet経由で追加しましょう。
  • 常にパラメータを使用する: SQLインジェクション防止、構文エラー回避、データ型の安全性確保のために、値をSQL文に直接埋め込まず、必ずパラメータを使用してください。
  • Using ステートメントを活用する: SQLiteConnection, SQLiteCommand, SQLiteDataReader, SQLiteTransaction などの IDisposable を実装したオブジェクトは、必ず Using ステートメントで囲んでください。これにより、リソースの解放忘れを防ぎ、アプリケーションの安定性を高めます。
  • 適切なエラーハンドリングを行う: データベース操作は失敗する可能性があります。Try...Catch ブロックでエラーを捕捉し、ユーザーにわかりやすいメッセージを表示したり、ログに記録したりするなどの適切な対応を行ってください。トランザクションを使用している場合は、エラー発生時に必ずロールバックを呼び出してください。
  • 接続は必要な時に開き、完了したらすぐに閉じる: データベース接続はリソースを消費し、ファイルロックの原因にもなります。接続は操作の直前に開き、操作が完了したらすぐに閉じるようにしてください。Using ステートメントを使えば、この管理を自動化できます。
  • SELECT文では取得する列を明示する (SELECT * は避けるべきか検討する): SELECT * は手軽ですが、テーブル構造の変更に弱く、不要なデータまで取得してパフォーマンスに影響を与える可能性があります。特に必要がない限り、取得したい列を明示的に指定するのが良いプラクティスです。
  • 適切なデータ型を選択する: SQLiteは動的な型付けの側面を持ちますが、意図するデータの種類に合わせて適切な型(INTEGER, REAL, TEXT, BLOB)を指定することで、データの整合性を保ちやすくなります。日付や時刻はTEXT形式での格納が一般的です。
  • トランザクションが必要な操作を特定し、適切に適用する: 複数の関連するデータベース操作は、トランザクションで囲むことでデータの整合性を保証できます。
  • データベースファイルの配置場所を検討する: データベースファイルをアプリケーションの実行ファイルと同じディレクトリに置くのは手軽ですが、WindowsではProgram Filesのような場所にアプリケーションをインストールした場合、書き込み権限の問題が発生する可能性があります。ユーザー固有の設定やデータであれば、Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)などで取得できるアプリケーションデータフォルダ内に配置するのが推奨されます。
  • シンプルなSQLから始める: まずは基本的なCRUD操作をパラメータを使って確実に実装できるようになりましょう。必要に応じてJOINやサブクエリなどの複雑なクエリに進んでください。

まとめ

本記事では、VB.NETアプリケーションからSQLiteデータベースを操作するための基本的な手法を詳細に解説しました。

  • SQLiteは、軽量で配布が容易なファイルベースのデータベースであり、VB.NETデスクトップアプリケーションに非常に適しています。
  • NuGetパッケージ「System.Data.SQLite」を追加することで、VB.NETからSQLiteへアクセスできます。
  • SQLiteConnection クラスでデータベースファイルに接続し、Open() で開き、Close() または Using で閉じます。接続文字列でデータベースファイルのパスを指定します。
  • SQLiteCommand クラスにSQL文を設定し、ExecuteNonQuery() (INSERT, UPDATE, DELETE, CREATE TABLEなど)、ExecuteReader() (SELECT), ExecuteScalar() (単一値SELECT) で実行します。
  • データの挿入、更新、削除、選択といった基本的なCRUD操作には、対応するSQL文 (INSERT INTO, UPDATE, DELETE FROM, SELECT) を使用します。
  • セキュリティと安全性のために、SQL文に値を直接埋め込まず、必ずパラメータを使用してください。
  • 複数の関連する操作を原子的に扱うためには、BeginTransaction(), Commit(), Rollback() を使ったトランザクション処理が必要です。
  • エラーハンドリングには Try...Catch を使用し、リソース管理には Using ステートメントを使用するのがベストプラクティスです。

これらの基本的な知識とコード例を参考にすることで、VB.NETアプリケーションにSQLiteデータベースを組み込み、データの永続化を実現できるようになるはずです。SQLiteは非常に多機能なデータベースエンジンであり、本記事で扱った内容は基本的な部分に過ぎません。さらに複雑なクエリ、インデックス、ビュー、トリガーなど、応用的な機能も多数存在します。

まずは基本をしっかりと押さえ、実際にコードを書いて動作を確認しながら理解を深めていくことをお勧めします。SQLiteをVB.NET開発に活用し、より機能的で便利なアプリケーションを作成してください。

Happy Coding!


コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

上部へスクロール