質問するログイン新規登録

Q&A

解決済

1回答

198閲覧

パラメータを使用したSQL文を実行したときのエラー

Hiro987654

総合スコア2

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

SQLite

SQLiteはリレーショナルデータベース管理システムの1つで、サーバーではなくライブラリとして使用されている。

0グッド

0クリップ

投稿2025/12/18 08:36

編集2025/12/19 05:35

0

0

実現したいこと

C#(.NET Framework4.8.1)とSQLiteを使用したアプリケーションを作っています。
JSONファイルから読み込んだデータをテーブルにインサートする部分で詰まっています。

発生している問題・分からないこと

ファイルから読み取った値を、パラメータとしてCommandTextに渡しているのですが、SQL文の実行時にエラーが出ます。
エラーメッセージは「パラメータが渡されていない」と言っているのですが、ブレークポイントを置いて確認したところ、意図した数のパラメータが渡されていました。

エラーメッセージ

error

1System.InvalidOperationException: 'Must add values for the following parameters: '

該当のソースコード

C#

1 // -------------------------- 2 // JSONファイルの読み込み 3 // -------------------------- 4 5 private List<dynamic> ReadJSONFile(string JSONFilePath) 6 { 7 List<dynamic> result = new List<dynamic>(); 8 9 if (File.Exists(JSONFilePath)) 10 { 11 string JsonData=File.ReadAllText(JSONFilePath); 12 result=JsonConvert.DeserializeObject<List<dynamic>>(JsonData); 13 } 14 return result; 15 }

C#

1 // -------------------------- 2 // 指定されたテーブルにインサート 3 // -------------------------- 4 5 private void SetDBData(string TableName, List<dynamic> dbData) 6 { 7 using (var conn = new SqliteConnection($"Data Source={databasePath}")) 8 { 9 conn.Open(); 10 using (var tran = conn.BeginTransaction()) 11 { 12 var cmd = conn.CreateCommand(); 13 int counter = 0; 14 15 switch (TableName) 16 { 17 case "chip_type_table": 18 cmd.CommandText = "insert into chip_type_table(chip_type_id,type_name,chip_id,mask_value) " + 19 "values(@chip_type_id,@type_name,@chip_id,@mask_value)"; 20 foreach (dynamic x in dbData) 21 { 22 cmd.Parameters.Add(new SqliteParameter("@chip_type_id", x.chip_type_id.ToString())); 23 cmd.Parameters.Add(new SqliteParameter("@type_name", x.type_name.ToString())); 24 cmd.Parameters.Add(new SqliteParameter("@chip_id", x.chip_id.ToString())); 25 cmd.Parameters.Add(new SqliteParameter("@mask_value", x.mask_value.ToString())); 26 counter++; 27 28 if (counter % 100 == 0 || counter == dbData.Count) 29 { 30 int result = cmd.ExecuteNonQuery(); //ここでエラー 31 if (result == 0) 32 { 33 cmd.Parameters.Clear(); 34 } 35 else 36 { 37 tran.Rollback(); 38 return; 39 } 40 } 41 } 42 break; //この後にcase文で同様の処理が続きます 43 } 44 45 tran.Commit(); 46 } 47 conn.Close(); 48 } 49 }

C#

1 // -------------------------- 2 // ボタンを押して実行 3 // -------------------------- 4 private void Tourokubutton_Click(object sender, EventArgs e) 5 { 6 SetDBData("chip_type_table", ReadJSONFile(FilePathtextBox.Text)); 7 } 8 9

試したこと・調べたこと

  • teratailやGoogle等で検索した
  • ソースコードを自分なりに変更した
  • 知人に聞いた
  • その他
上記の詳細・結果

同様のエラーメッセージが出る事例を見つけました。解決方法はEntity Framework Coreを使用するというものでした。
私の場合は、.NET Framework4.8.1で開発をしているため、Entity Framework Coreを使用することができませんでした。

補足

【新たに試したこと1】
YT0014さまのコメントをもとに修正しました。
テーブルのデータ型と合わせた型にパラメータを変更しました。
解決はせず、同様のエラーメッセージが表示されます。

C#

1インサート用の関数を修正(22行目) 2cmd.Parameters.Add(new SqliteParameter("@chip_type_id",(int)x.chip_type_id )); 3cmd.Parameters.Add(new SqliteParameter("@chip_type_id",int.Parse(x.chip_type_id.ToString())));

【新たに試したこと2】
新たにChipTypeTableクラスを作りました。DBのテーブルに合わせた内容になっています。

C#

1 public class ChipTypeTable 2 { 3 public int chip_type_id { get; set; } 4 public string type_name { get; set; } 5 public string chip_id { get; set; } 6 public string mask_value { get; set; } 7}

また、読み込んだJSONファイルの内容をデシリアライズするとき、デシリアライズの結果の型をList<dynamic>にしていたのを、List<ChipTypeTable>に変更しました。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

YT0014

2025/12/19 00:19

SqliteParameterを、全て文字列型で作成されていますが、該当カラムも、全て文字列型なのでしょうか? 数値型など、別の型の場合、それに応じた型でパラメーターを作成する必要があるはずですが。 (コンストラクターの引数に SqliteType があるのは、その為) https://learn.microsoft.com/ja-jp/dotnet/api/microsoft.data.sqlite.sqliteparameter?view=msdata-sqlite-9.0.0
Hiro987654

2025/12/19 03:48 編集

コメントありがとうございます。 該当カラムのうちchip_type_idはINTEGERです。ですので、対応するパラメータをintに変換するように書き換えて試してみましたがまだ解決できていません。 試した結果を質問に追記します。
bebebe_

2025/12/19 06:43 編集

1レコードずつ追加するのはだめなんですか? まとめて複数のレコードを追加しているのが原因だと思われます。
Hiro987654

2025/12/19 07:39

コメントありがとうございます。    if (counter % 100 == 0 || counter == ListData.Count) のところをコメント行にするとインサートが実行されました。 このことから、今回のソースコードでは、実際に作られるSQL文は複数行をインサートするものではなく、1つの行に複数行分の値がインサートされるものになっていたのでエラーになっていた、ということかと考えています。 この行は、大量のデータがファイルから読み込まれた場合を想定して、 insert into table (A, B, C) values ('A1', 'B1', 'C1'), ('A2', 'B2', 'C2'),… のようなSQL文を実行することを意図していました。 調べたところ、上記のようなSQL文が使えるのはSQLite v3.7.11以降でした。私が使用しているMicrosoft.Data.Sqlite v10.0.1が使用しているSQLiteのバージョンは3.46.1で、この方法は使えないということがわかりました。 microsoftのドキュメントを見ると、 https://learn.microsoft.com/ja-jp/dotnet/standard/data/sqlite/bulk-insert >SQLite には、データを一括挿入する特別な方法はありません。 とありました。 ありがとうございました。
Hiro987654

2025/12/19 07:47

bebebe_さま ベストアンサーに選びたいので同じ内容を回答欄に投稿いただけますでしょうか?
bebebe_

2025/12/19 07:58

自己解決として締めてもらって構いませんよ。
guest

回答1

0

自己解決

bebebe_さまのコメントをもとに、

C#

1 if (counter % 100 == 0 || counter == ListData.Count)

のところをコメント行にするとインサートが実行されました。

このことから、今回のソースコードでは、実際に作られるSQL文は複数行をインサートするものではなく、1つの行に複数行分の値がインサートされるものになっていたのでエラーになっていた、ということかと考えています。

この行は、大量のデータがファイルから読み込まれた場合を想定して、

SQL

1insert into table (A, B, C) 2values ('A1', 'B1', 'C1'), 3('A2', 'B2', 'C2'),

のようなSQL文を実行することを意図していました。
調べたところ、上記のようなSQL文が使えるのはSQLite v3.7.11以降でした。私が使用しているMicrosoft.Data.Sqlite v10.0.1が使用しているSQLiteのバージョンは3.46.1で、この方法は使えないということがわかりました。
microsoftのドキュメントを見ると、
https://learn.microsoft.com/ja-jp/dotnet/standard/data/sqlite/bulk-insert
>SQLite には、データを一括挿入する特別な方法はありません。
とありました。

投稿2025/12/19 09:06

Hiro987654

総合スコア2

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.29%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問