https://docs.microsoft.com/ja-jp/dotnet/api/system.data.sqlclient.sqldataadapter.insertcommand?redirectedfrom=MSDN&view=dotnet-plat-ext-3.1#System_Data_SqlClient_SqlDataAdapter_InsertCommand
CommandBuilderは、主キーが存在しないテーブルのupdateコマンドを生成できないため、主キーが存在しないテーブルをDataAdapter+CommandBuilderで更新しようとすると「InvalidOperationException: DataAdapterのUpdateで UpdateCommand の動的 SQL 生成は、キーである列情報を返さないSelectCommand に対してサポートされていません。」
というシステムエラーが発生する。
対策は自前で生成したCommandオブジェクトをdataAdapter.UpdateCommandにセットすること。
……見つけられていないが、なんか一意の列を指定するだけでupdateコマンドを生成できるようなもっと上手い方法がありそうな気がする。
ちなみにInsert文は主キーが存在しないテーブルでも生成できるようだ。
あと、そもそも主キーが無いテーブルを作るなという話ではある。
' objAdpt のデータアダプタでno_key_tableテーブルの内容を、objTblにデータをFillした状態。
Dim objCmdBld As New NpgsqlCommandBuilder(objAdpt)
objAdpt.InsertCommand = objCmdBld.GetInsertCommand()
objAdpt.UpdateCommand = Me.CreateUpdateCommand(objAdpt.InsertCommand.Connection)
Call objAdpt.Update(objTbl)
Private Function CreateUpdateCommand(objConnection As NpgsqlConnection) As NpgsqlCommand
Dim strSql = ""
strSql &= "UPDATE no_key_table"
strSql &= " SET col1 = :paraCol1"
strSql &= " , col2 = :paraCol2"
strSql &= " WHERE key1 = :paraKey1" ' 主キーとしては設定されていないが、key1,key2で一意になる想定
strSql &= " AND key2 = :paraKey2"
Dim objCmd = New NpgsqlCommand(strSql, objConnection)
objCmd.Parameters.Add(New NpgsqlParameter() With {.ParameterName = "paraCol1", .SourceColumn = "col1"})
objCmd.Parameters.Add(New NpgsqlParameter() With {.ParameterName = "paraCol2", .SourceColumn = "col2"})
objCmd.Parameters.Add(New NpgsqlParameter() With {.ParameterName = "paraKey1", .SourceColumn = "key1"})
objCmd.Parameters.Add(New NpgsqlParameter() With {.ParameterName = "paraKey2", .SourceColumn = "key2"})
Return objCmd
End Function