我遇到了一个问题,我想插入一个有标识列的表。我正在使用命令构建器来实现此目的。但是当命令构建器构建Insertion命令时,它不包含其中的标识列(其余列都在那里)。我被迫手动插入标识列。我该如何继续将标识列添加到我的插入命令中?
SqlDataAdapter da = null;
SqlCommandBuilder cmdBuilder = null;
DataSet dsSourceTable = LoadData(query, SourceCn, ref da, "dsMigratedData", table, ref cmdBuilder);
da.InsertCommand = cmdBuilder.GetInsertCommand();
da.InsertCommand.Connection = DestCn;
但是我也用过这个
da.InsertCommand.Parameters.Add(new SqlParameter("AppointmentID", SqlDbType.Int));
最后
cmd = new SqlCommand("SET IDENTITY_INSERT Appointment ON", DestCn, transaction);
cmd.ExecuteNonQuery();
foreach (DataRow row in dsSourceTable.Tables[table].Rows)
{
foreach (SqlParameter p in da.InsertCommand.Parameters)
{
p.Value = row[p.SourceColumn];
}
da.InsertCommand.ExecuteNonQuery();
}
答案 0 :(得分:3)
澄清这个问题的原因和原因: 这种情况可能更好地说明您可能需要执行以下操作的原因:
将服务器数据与嵌入式数据库(Sqlite)同步。将更改从客户端推送到服务器,然后将更改下载到客户端(upsert)。
在这种情况下,CommandBuilder需要包含来自SQL Server源表的整数主键,即BIGINT IDENTITY,以及Sqlite中的INT AUTOINCREMENT(在SQLite3中,INTEGER ROWID列是INT64,因此SQL Server必须是BIGINT才能匹配)。
现在,在Sqlite中,您可以在插入时指定PK列并将其接受;您不必执行任何类似SET IDENTITY_INSERT ON的操作。所以你真的只需要insert命令中的PK列。
你可以使用上面的代码混搭一些东西,但是让CommandBuilder以某种方式包含主键会非常简单。
This thread谈到手动黑客攻击InsertCommand.CommandText属性,但在我看来这太糟糕了。
调用da.Update()可能存在问题。 this thread中的较低帖子表示ADO可能会擦除任何手动参数添加,并通过在调用Update()之前复制dataadapter来提供解决方案。另一个线程讲述了有人遇到这个问题的故事(虽然没有在该线程上解析)。
所以,经过多次讨论之后,我想出了关于Sqlite的内容:如果表使用AUTOINCREMENT作为主键,而不是允许整数主键的默认行为(当没有主键列时自动执行加号)在插入时指定),那么您不能为主键插入自己的值。
我的最终解决方案,因为我没时间,就是做了here所描述的内容,即我从本地Sqlite数据库中删除了AUTOINCREMENT,攻击了InsertCommand.CommandText并手动添加了主键列作为常规参数(不将其添加为主键):
SQLiteCommandBuilder commandBuilder = new SQLiteCommandBuilder();
commandBuilder.DataAdapter = daLocal;
SQLiteCommand insertCommand = commandBuilder.GetInsertCommand(true);
insertCommand.CommandText = insertCommand.CommandText.Replace("] (", "] ([id], ");
insertCommand.CommandText = insertCommand.CommandText.Replace("VALUES (", "VALUES (@id, ");
SQLiteParameter pkParam = new SQLiteParameter("id", DbType.Int64, "id");
insertCommand.Parameters.Add(pkParam);
daLocal.InsertCommand = insertCommand;
这样就可以将源SQL Server表中的主键值插入到本地Sqlite表中。
最后,我找不到DataTable对象或我可以操作的SQLiteDataAdapter对象的属性,这会导致显式创建的SqliteCommandBuider或者编译成SQLiteDataAdapter的构建器为SQLiteDataAdapter.InsertCommand创建id列和参数。
祝你好运。答案 1 :(得分:-1)
数据库自己插入标识列...您不必在查询中包含identty列值。 如果出现问题,请获取命令构建器在运行时生成的值,并在数据库中执行它,看看究竟发生了什么 确保我们的查询顺序正确,因为它匹配表中列的顺序。