【发布时间】:2018-10-15 15:48:40
【问题描述】:
我正在尝试使用 SqlDataAdapter 插入一行,然后立即获取同一行。我遵循了this post 上的建议并使用了 SCOPE_IDENTITY,但它不起作用。这是我的代码...
using (var conn = _db.OpenConnection())
{
var sqlQuery = "SELECT * FROM RotationItem WHERE [RotationItemId] = SCOPE_IDENTITY()";
var adapter = new SqlDataAdapter(sqlQuery, conn);
var builder = new SqlCommandBuilder(adapter);
var dataSet = new DataSet();
adapter.Fill(dataSet);
Debug.WriteLine("First fill, rows " + dataSet.Tables[0].Rows.Count);
var table = dataSet.Tables[0];
table.Rows.InsertAt(table.NewRow(), 0);
CopyJsonToRow(table, 0, item);
if (adapter.Update(dataSet) != 1)
{
throw new InvalidOperationException("Insert failed");
}
// After insert, fetch the new record
dataSet.Clear();
adapter.Fill(dataSet);
Debug.WriteLine("Second fill, rows " + dataSet.Tables[0].Rows.Count);
}
我的输出是:
- 第一次填充,第 0 行
- 第二次填充,第 0 行
为什么第二次填充失败?它不应该得到我刚刚插入的行吗?!
我没有使用任何交易。表的定义如下...
CREATE TABLE [dbo].[RotationItem] (
[RotationItemId] INT NOT NULL IDENTITY(1,1),
[RotationScheduleId] INT NOT NULL,
[QuestionnaireId] INT NOT NULL,
[Order] INT NOT NULL,
PRIMARY KEY CLUSTERED ([RotationItemId] ASC)
);
【问题讨论】:
-
SCOPE_IDENTITY 在同一个会话上工作。我怀疑您的插入可能在不同的会话中,因此后续的 SCOPE_IDENTITY 将没有任何返回。您可以在执行此操作时运行探查器跟踪来进行验证,并查看 session_id 值返回什么。更好的方法是使用存储过程插入行并将 SCOPE_IDENTITY 值作为输出参数返回
-
@MartinCairney 我认为您是正确的,因为当我将查询更改为使用
IDENT_CURRENT('RotationItem')而不是SCOPE_IDENTITY()时,它就可以工作了!!但是,如果许多插入同时在不同的线程上运行,它通常会给出错误的答案。太糟糕了。 -
这里是关于使用 ADO.NET 检索身份值的文档页面:docs.microsoft.com/en-us/dotnet/framework/data/adonet/…
-
@DavidBrowne-Microsoft 谢谢,但该页面对我没有帮助,因为我使用的是
SqlCommandBuilder。您认为使用 SqlCommandBuilder 是不可能的吗?我尝试将“;SELECT SCOPE_IDENTITY()”附加到builder.GetInsertCommand().CommandText的末尾,但它没有效果。我尝试设置adapter.InsertCommand,但没有效果。创建 SqlCommandBuilder 后,我似乎根本无法自定义它。
标签: c# sql-server ado.net sqldataadapter