【C#】C#でSqliteをささっと使いたい時の備忘録

# C#でささっとSqliteを使いたい時の備忘録

ちょっとしたデータを加工する時にシェル芸やら何やら手段は色々ありますが、
個人的にはC#+Sqliteでササっと使い捨てを書くのもよくやります。

記憶力減退著しい自分のために「とりあえずSqliteでDBを作ってSQL発行できる」くらいのところを目指して記録します。

# 環境
.Net 4.6.2 + C#、コンソールアプリ。

# 前提
理解するためのサンプルソースということでエラー処理は皆無です。
参考にする場合はエラー処理の配慮を各自お願いします。

SQLについて説明皆無です。

# GitHub

まるっと、はこちらをCloneしてください。

https://github.com/fu-foo/SqliteCSharpSimpleSample

# ソース全景

<details><summary>ソースコードを表示（折りたたみ）</summary><div>

``` C#:Program.cs
using System;
using System.Data.SQLite;

namespace Fu.SqliteCSharpSimpleSample
{
	internal class Program
	{
		static void Main(string[] args)
		{
			// (1)DB作成
			Console.WriteLine("■DB作成");

			// ファイル作成(既に同じファイル名であれば初期化される)
			//SQLiteConnection.CreateFile(@"c:\temp\test.db");

			var sqlConnStr = new SQLiteConnectionStringBuilder
			{
				// メモリー上に展開
				DataSource = ":memory:"
				// 既存DBを読む場合
				//DataSource = @"c:\temp\test.db"

			};

			using (var conn = new SQLiteConnection(sqlConnStr.ToString()))
			{
				// (2)接続
				Console.WriteLine("■DB接続");
				conn.Open();

				using (var cmd = new SQLiteCommand(conn))
				{
					// (3)create table
					Console.WriteLine("■create table");
					cmd.CommandText = "create table if not exists user(id integer primary key, name text, updttm text)";
					cmd.ExecuteNonQuery();

					// (4)insert x 3
					Console.WriteLine("■insert x 3");
					cmd.CommandText = "insert into user(id, name, updttm) values(1,'hoge', '2022-10-26')";
					cmd.ExecuteNonQuery();
					cmd.CommandText = "insert into user(id, name, updttm) values(2,'fuga', '2022-10-27')";
					cmd.ExecuteNonQuery();
					cmd.CommandText = "insert into user(id, name, updttm) values(3,'piyo', '2022-10-28')";
					cmd.ExecuteNonQuery();

					// (5)トランザクションありのinsert
					Console.WriteLine("■insert with transation");
					var tran = conn.BeginTransaction();

					Console.WriteLine("■パラメーター指定のinsert");
					cmd.CommandText = "insert into user(id, name, updttm) values(@id, @name, @updttm)";
					cmd.Parameters.Add(new SQLiteParameter("@id", 4));
					cmd.Parameters.Add(new SQLiteParameter("@name", "poco"));
					cmd.Parameters.Add(new SQLiteParameter("@updttm", "2024-01-01"));
					if (cmd.ExecuteNonQuery() != 1)
					{
						Console.WriteLine("■トランザクション失敗はロールバック");
						tran.Rollback();
						return;
					}
					Console.WriteLine("■コミット");
					tran.Commit();

					// (6)select
					Console.WriteLine("■select");
					cmd.CommandText = "select * from user";
					using (var reader = cmd.ExecuteReader())
					{
						while (reader.Read())
						{
							Console.WriteLine($"id={reader["id"].ToString()} name={reader["name"]} updttm={reader["updttm"]}");
						}
					}

					// (7)パラメーター指定のselect
					Console.WriteLine("■パラメーター指定のselect");
					cmd.CommandText = "select * from user where id = @id";
					cmd.Parameters.Add(new SQLiteParameter("@id", 1));
					var result = cmd.ExecuteNonQuery();
					using (var reader = cmd.ExecuteReader())
					{
						while (reader.Read())
						{
							Console.WriteLine($"id={reader["id"].ToString()} name={reader["name"]} updttm={reader["updttm"]}");
						}
					}
				}

				// (8)close
				Console.WriteLine("■close");
				conn.Close();
			}
		}
	}
}

```

</div></details>

# Nuget

System.Data.SQLite.Coreを取得。
一緒に必要なものも落ちてきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138460/9a092333-fc4d-d194-6523-5e0b45d2c9f0.png)

# ソース解説

Mainの中で順次実行していきます。

1. DB作成
1. 接続
1. create table
1. insert
1. トランザクションありのinsert
1. select
1. パラメーター指定のselect
1. close

## (1)DB作成

コメントアウトしてますがSQLiteConnection.CreateFileで新規DBを作成できます。
既存ファイルがある場合新規作成になるのでご注意を。

DataSourceで取得元を指定。
":memory:"指定であればオンメモリで展開されます。

``` C#:Program.cs
~~省略~~
			// (1)DB作成
			Console.WriteLine("■DB作成");

			// ファイル作成(既に同じファイル名であれば初期化される)
			//SQLiteConnection.CreateFile(@"c:\temp\test.db");

			var sqlConnStr = new SQLiteConnectionStringBuilder
			{
				// メモリー上に展開
				DataSource = ":memory:"
				// 既存DBを読む場合
				//DataSource = @"c:\temp\test.db"

			};
~~省略~~
```

## (2)接続

こちらは素直にOPENするだけ。
``` C#:Program.cs
~~省略~~
			using (var conn = new SQLiteConnection(sqlConnStr.ToString()))
			{
				// (2)接続
				Console.WriteLine("■DB接続");
				conn.Open();
~~省略~~
```

## (3)create table

SQLの説明は割愛です。
CommandTextにcreate文を定義して、ExecuteNonQueryで実行です。

``` C#:Program.cs
~~省略~~
				using (var cmd = new SQLiteCommand(conn))
				{
					// (3)create table
					Console.WriteLine("■create table");
					cmd.CommandText = "create table if not exists user(id integer primary key, name text, updttm text)";
					cmd.ExecuteNonQuery();
~~省略~~
```

## (4)insert

CommandTextにベタにインサート文全文を書いてからの、ExecuteNonQuery実行です。

``` C#:Program.cs
~~省略~~
					// (4)insert x 3
					Console.WriteLine("■insert x 3");
					cmd.CommandText = "insert into user(id, name, updttm) values(1,'hoge', '2022-10-26')";
					cmd.ExecuteNonQuery();
					cmd.CommandText = "insert into user(id, name, updttm) values(2,'fuga', '2022-10-27')";
					cmd.ExecuteNonQuery();
					cmd.CommandText = "insert into user(id, name, updttm) values(3,'piyo', '2022-10-28')";
					cmd.ExecuteNonQuery();
~~省略~~
```

## (5)トランザクションありのinsert

BeginTransaction～Rollback or Commitの記述です。
例として書いたものの(4)のSQL直は避けるべきなので、このinsertはパラメーター指定でのinsertにしています。

``` C#:Program.cs
~~省略~~
					// (5)トランザクションありのinsert
					Console.WriteLine("■insert with transation");
					var tran = conn.BeginTransaction();

					Console.WriteLine("■パラメーター指定のinsert");
					cmd.CommandText = "insert into user(id, name, updttm) values(@id, @name, @updttm)";
					cmd.Parameters.Add(new SQLiteParameter("@id", 4));
					cmd.Parameters.Add(new SQLiteParameter("@name", "poco"));
					cmd.Parameters.Add(new SQLiteParameter("@updttm", "2024-01-01"));
					if (cmd.ExecuteNonQuery() != 1)
					{
						Console.WriteLine("■トランザクション失敗はロールバック");
						tran.Rollback();
						return;
					}
					Console.WriteLine("■コミット");
					tran.Commit();
~~省略~~
```

## (6)select 

CommandTextにselect文を書いてExecuteReaderで実行、Readで1行ずつ読み出します。

``` C#:Program.cs
~~省略~~
					// (6)select
					Console.WriteLine("■select");
					cmd.CommandText = "select * from user";
					using (var reader = cmd.ExecuteReader())
					{
						while (reader.Read())
						{
							Console.WriteLine($"id={reader["id"].ToString()} name={reader["name"]} updttm={reader["updttm"]}");
						}
					}
~~省略~~
```

## (7)パラメーター指定のselect

繰り返しになりますがSQLベタ書きは避けて、パラメーター指定のselectです。
SQLiteParameterでパラメーター指定をする以外は(6)のselectと同じ。

``` C#:Program.cs
~~省略~~
					// (7)パラメーター指定のselect
					Console.WriteLine("■パラメーター指定のselect");
					cmd.CommandText = "select * from user where id = @id";
					cmd.Parameters.Add(new SQLiteParameter("@id", 1));
					var result = cmd.ExecuteNonQuery();
					using (var reader = cmd.ExecuteReader())
					{
						while (reader.Read())
						{
							Console.WriteLine($"id={reader["id"].ToString()} name={reader["name"]} updttm={reader["updttm"]}");
						}
					}
```

## (8)close

usingで囲ってはありますが、ここでcloseしているよというのを伝えるために明示的に書くほうが好きです。

``` C#:Program.cs
~~省略~~
				// (8)close
				Console.WriteLine("■close");
				conn.Close();
```

# 実行結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138460/ca8ee6a2-89f1-c075-ddd4-d9262616b058.png)

# 注意点

GitHubからCloneしてきて即ビルドして実行すると、SQLite.Interop.dllが無いと怒られるかもしれません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138460/eeffd962-4b0a-a07c-70ff-71bd20c0e21c.png)



package以下にSQLite.Interop.dllが入っているx86,x64フォルダーがあるのでexeが作成されるフォルダーにまるっとコピーをお願いします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138460/af55e398-19a0-74c1-075a-3c85decd868a.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138460/9f9b42c5-0b5e-f665-3021-d092d5fe699f.png)