人が作ったC#のソースを保守していて、データクラスに項目を 1つ追加し単体試験した際、「Microsoft.Data.SqlClient.SqlException: ‘3 列が指定されたテーブル値パラメーターを渡そうとしていますが、対応するユーザー定義テーブル型では 2 列が必要です。’」例外が発生しドハマりした。
結果的には、C#側のデータクラスに項目を追加するだけでは足りず、対になっていた SQLServer側の ユーザー定義テーブル型にも項目を追加していなかったのが原因。
C#のソースコード側からは、SQLServer側に対になるユーザー定義テーブル型があるようには全く見えずドハマりした。
C#側のデータクラス
項目追加前のデータクラス
1 2 3 4 5 6 7 |
public class ImportDuplication { [Key("RowNumber")] public int RowNumber { get; set; } [Key("CustomerId")] public int? CustomerId { get; set; } } |
項目追加後のデータクラス
1 2 3 4 5 6 7 8 |
public class ImportDuplication { [Key("RowNumber")] public int RowNumber { get; set; } [Key("CustomerId")] public int? CustomerId { get; set; } [Key("RecordedAt")] public DateTime? RecordedAt { get; set; } } |
対応する SQLServer側のユーザー定義テーブル型
項目追加前のユーザー定義テーブル型
1 2 3 4 5 6 7 8 9 10 |
CREATE TYPE [dbo].[ImportDuplication] AS TABLE( [RowNumber] [int] NOT NULL, [CustomerId] [int] NULL, PRIMARY KEY CLUSTERED ( [RowNumber] ASC )WITH (IGNORE_DUP_KEY = OFF) ) |
項目追加後のユーザー定義テーブル型
1 2 3 4 5 6 7 8 9 10 11 |
CREATE TYPE [dbo].[ImportDuplication] AS TABLE( [RowNumber] [int] NOT NULL, [CustomerId] [int] NULL, [RecordedAt] [date] NULL, PRIMARY KEY CLUSTERED ( [RowNumber] ASC )WITH (IGNORE_DUP_KEY = OFF) ) |
SQL実行処理
「Microsoft.Data.SqlClient.SqlException: ‘3 列が指定されたテーブル値パラメーターを渡そうとしていますが、対応するユーザー定義テーブル型では 2 列が必要です。’」例外が発生した、Dapper dbHelper.GetItems() を通してSQL実行している処理。
1 2 3 4 5 6 7 8 9 10 11 |
public IEnumerable<int> ImportDuplicationCheck(IEnumerable<ImportDuplication> ImportDuplication) { var query = $@" SELECT d.RowNumber FROM @ImportDuplication d "; return dbHelper.GetItems<int>(query, new { ImportDuplication = ImportDuplication.GetTableParameter() }).ToArray(); } |
コメント