C# 添加表的标识列插入命令

发布于 2024-11-30 20:36:53 字数 890 浏览 1 评论 0原文

我遇到了一个问题,我想插入到具有标识列的表中。我正在使用命令生成器来实现此目的。但是,当命令生成器生成插入命令时,它不包含标识列(其余列都在那里)。我被迫手动插入到身份列中。我应该如何继续将标识列添加到我的插入命令中?

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();
 }

I am stuck with a problem where i want to insert into a table which has an identity column. I am using command builder for this purpose. But when command builder builds the Insertion command, it does not contain the identity column in it(rest of the columns are there). I am forced to insert manually into identity column. How should I proceed to get identity column into my Insertion Command?

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;

However I also used this

da.InsertCommand.Parameters.Add(new SqlParameter("AppointmentID", SqlDbType.Int));

and finally

 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();
 }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

妖妓 2024-12-07 20:36:53

澄清这个问题的原因和理由:
这种情况可能会更好地说明为什么您可能需要执行所要求的操作:

将服务器数据与嵌入式数据库 (Sqlite) 同步。将更改从客户端推送到服务器,然后将更改下载到客户端(更新插入)。

在这种情况下,CommandBuilder 需要包含来自 SQL Server 源表的整数主键,即 BIGINT IDENTITY,以及 Sqlite 中的 INT AUTOINCRMENT(在 SQLite3 中,INTEGER ROWID 列是 INT64,因此 SQL Server 必须是 BIGINT 才能匹配)。

现在,在 Sqlite 中,您可以在插入时指定 PK 列,并且它会接受它;您不必执行 SET IDENTITY_INSERT ON 之类的操作。所以你实际上只需要插入命令中的 PK 列。

您可以使用上面的代码混合某些内容,但让 CommandBuilder 以某种方式包含主键确实要简单得多。

此主题谈论手动破解 InsertCommand.CommandText 属性,但在我看来,它太破解了。

调用 da.Update() 可能存在问题。 此线程中的较低帖子指示 ADO 可能会擦除任何手动添加的参数,并通过在调用 Update() 之前复制数据适配器来提供解决方案。另一个线程讲述了有人遇到这个问题的故事(尽管该线程没有解决方案)。

因此,经过一番思考后,我发现了关于 Sqlite 的问题:如果表使用 AUTOINCRMENT 作为主键,而不是允许整数主键的默认行为(当插入时没有指定主键列时自动加一) ),那么您就无法为主键插入您自己的值。

我的最终解决方案,因为我没时间了,就是执行所描述的操作 这里,就是我从本地去掉了AUTOINCRMENT Sqlite 数据库,破解 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 列和参数。

祝你好运。

Clarification of the whys-and-wherefores of this question:
This situation might better illustrate why you might need to do what is asked for:

Sync server data with an imbedded database (Sqlite). Push changes from client up to server and then download changes to client (upsert).

In this case, CommandBuilder needs to include the integer primary key from the SQL Server source table, which is BIGINT IDENTITY, and INT AUTOINCREMENT in Sqlite (in SQLite3, INTEGER ROWID columns are INT64, so SQL Server must be BIGINT to match).

Now, in Sqlite, you can specify the PK column on insert and it takes it;, you don't have to do anything like SET IDENTITY_INSERT ON. So you really just need the PK column in the insert command.

You can mash up something using the code above, but it would have been really much simpler to have CommandBuilder include the primary key somehow.

This thread talks about manually hacking the InsertCommand.CommandText property, but that it too hack-ish, in my opinion.

There might be an issue calling da.Update(). A lower post in this thread indicates ADO might wipe any manual parameter adding, and offers a solution by copying the dataadapter before calling Update(). Another thread tells the tale of whoa of someone running into this problem (no resolution on that thread though).

So, after much mucking around, I figured out this about Sqlite: If the table uses AUTOINCREMENT for the primary key, instead of allowing the default behavior for an integer primary key (automatically does a plus-one when no primary key column specified on insert), then you can't insert your own value for the primary key.

My ultimate solution, because I ran out of time, was to do what was described here, that is I removed AUTOINCREMENT from the local Sqlite database, hacked InsertCommand.CommandText and manually adding the primary key column as a regular parameter (not adding it as a primary key):

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;

This gave the desired affect of inserting primary key values from the source SQL Server table into the local Sqlite table.

In the end I failed to find a property of either the DataTable object or the SQLiteDataAdapter object that I could manipulate that would cause either an explictly created SqliteCommandBuider or the builder baked into SQLiteDataAdapter create the id column and parameter for SQLiteDataAdapter.InsertCommand.

Good luck.

那伤。 2024-12-07 20:36:53

数据库自行插入标识列...您不必在查询中包含标识列值。
如果出现问题,请尝试获取命令生成器在运行时生成的值并在数据库中执行它,看看到底发生了什么
确保我们的查询顺序正确,因为它与表中列的顺序匹配。

database inserts Identity columns byitself...you dont have to include identty column value in your query.
If problems are coming try,take the value that your command builder is generating in runtime and execute it in database and see what exactly is happening
Make sure our query is in right sequence as in it matches the sequence of column in your table.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文