SqlCommandBuilder是否可以在插入时检索IDENTITY列的值(而无需使用存储过程)?

15
FYI:我正在运行dotnet 3.5 SP1
我正在尝试在使用SqlDataAdapter和SqlCommandBuilder执行更新后,从我的数据集中检索标识列的值。在执行SqlDataAdapter.Update(myDataset)之后,我想能够读取myDataset.tables(0).Rows(0)("ID")的自动分配值,但它是System.DBNull(尽管已插入该行)。
(注意:我不想显式编写新的存储过程来完成此操作!)
经常发布的一种方法http://forums.asp.net/t/951025.aspx修改SqlDataAdapter.InsertCommand和UpdatedRowSource,如下所示:
SqlDataAdapter.InsertCommand.CommandText += "; SELECT MyTableID = SCOPE_IDENTITY()"
InsertCommand.UpdatedRowSource = UpdateRowSource.FirstReturnedRecord

显然,这似乎在过去对许多人有效,但对我无效。

另一种技术:http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=619031&SiteID=1 对我也不起作用,因为执行SqlDataAdapter.Update后,SqlDataAdapter.InsertCommand.Parameters集合会重置为原始状态(丢失额外添加的参数)。

有人知道答案吗???


仅供参考:Code Project文章“使用SCOPE_IDENTITY与CommandBuilder和DataAdapter”是帮助我的解决方案。(我不是该文章的作者)。 - Uwe Keim
我知道这已经很老了,但在vs 2015中仍然存在很多错误。我遇到了同样的问题,并且已经使用了上面文章中的代码。对我来说,解决方法是将“set ID to SCOPE_IDENTITY()”重命名为“SET SCOPE_ID = SCOPE_IDENTITY()”。是的,我知道实际上没有什么区别,但现在它又可以正常工作了,原因不明。 - GuidoG
14个回答

0
问题在于,当使用SqlDataAdapter.Update(DataSet)方法时,您对InsertCommand所做的更改不会被考虑在内。 完美的解决方案是克隆由CommandBuilder生成的InsertCommand
SqlCommandBuilder cb = new SqlCommandBuilder(da);
cb.ConflictOption = ConflictOption.OverwriteChanges;

da.InsertCommand = cb.GetInsertCommand().Clone();
da.InsertCommand.CommandText += "; SELECT idTable = SCOPE_IDENTITY()";
da.InsertCommand.UpdatedRowSource = UpdateRowSource.FirstReturnedRecord;

da.Update(dt);

0
其实,这更容易,不需要任何自定义命令。当您在数据集设计器中创建tableadapter时,在向导的高级选项中指定“刷新数据表”。有了这个选项,在您发出dataadapter.update mydataset之后,您会发现数据表中的标识列已经填充了来自数据库的新值。

0

我的解决方案:

SqlDataAdapter da = new SqlDataAdapter("SELECT * FROM Mytable;" , sqlConnection);

SqlCommandBuilder cb = new SqlCommandBuilder(da);

da.DeleteCommand = (SqlCommand)cb.GetDeleteCommand().Clone();
da.UpdateCommand = (SqlCommand)cb.GetUpdateCommand().Clone();

SqlCommand insertCmd = (SqlCommand)cb.GetInsertCommand().Clone();

insertCmd.CommandText += ";SET @Id = SCOPE_IDENTITY();";
insertCmd.Parameters.Add("@Id", SqlDbType.Int, 0, "Id").Direction = ParameterDirection.Output;
da.InsertCommand = insertCmd;
da.InsertCommand.UpdatedRowSource = UpdateRowSource.OutputParameters;

cb.Dispose();

-1

你有考虑过使用LINQ吗?我知道这并没有回答你的实际问题,但如果你正在使用.NET 3.5,你真的应该尝试使用LINQ。事实上,随着Code First EntityFramework的出现,我认为你可以很容易地选择使用LINQ to SQL或EF作为相对轻量级的替代方案来代替自己编写数据访问层。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接