.Net SqlDataAdapter 在使用列上的默认值插入后检索身份
Posted
技术标签:
【中文标题】.Net SqlDataAdapter 在使用列上的默认值插入后检索身份【英文标题】:.Net SqlDataAdapter retrieve identity after insert with default value on column 【发布时间】:2018-07-09 12:11:48 【问题描述】:我需要一种在使用 SqlDataAdapter 插入后检索标识值的方法。
我测试了以下案例:
如果我在插入后运行 select @@identity,如果有其他触发器执行插入,则返回的值不正确。
如果我在插入后运行 select scope_identity(),它不是同一批,所以标识为空
解决方法是在同一批次中运行select scope_identity(),所以我修改了adapter的InsertCommand(见下面代码)
此时,我遇到了另一个问题:adapter.Update 重置了插入命令,所以它没有运行第二个选择(scope_identity())。 如果构建器使用 builder.RefreshSchema() 清理命令,则此问题得到解决,因为插入命令保持不变。另一方面, 如果插入是这样的:
adapter.InsertCommand.CommandText = "INSERT INTO [clinics].[InstutionContracts] ( [DateStart], [DateEnd], [ContractType], [DataDeTest]) VALUES (@p1, @p2, @p3, @p4);SELECT SCOPE_IDENTITY() as SkunkIdReturn"
SQL Server 列 DataDeTest 不允许空值,但它具有 getdate() 的默认值,因此它会抛出插入 NULL 值的异常(@p4 为 NULL)。 请记住,在这种情况下,我在 builder.RefreshSchema() 之前运行。如果我没有运行它,适配器将只更新前三列, 该行将被正确插入,但我没有在 table.Rows [0] 中获得标识。这是我的代码:
DbCommand command = null;
DbDataAdapter adapter = null;
command = new SqlCommand();
adapter = new SqlDataAdapter();
var factory = bProviderFactories.GetFactory("system.data.sqlclient");
var builder = factory.CreateCommandBuilder();
builder.DataAdapter = adapter;
DbCommand command2 = null;
command2 = new SqlCommand();
command2 = builder.GetInsertCommand();
builder.RefreshSchema();
command2.CommandText += ";SELECT SCOPE_IDENTITY() as SkunkIdReturn"; // get id
adapter.InsertCommand = command2;
var table = new DataTable(tableName);
retSupd.rows = new List<row>();
var lrv = new List<row>();
....
var identity = "";
if (isSqlServerConnection && curRow.status == Status.Nou)
adapter.InsertCommand.UpdatedRowSource = UpdateRowSource.Both;
adapter.Update(table);
identity = table.Rows[0][table.Rows[0].ItemArray.Length - 1].ToString(); // is retrieved only if there are not null values on default columns
// otherwise, it returns "cannot insert NULL value in not NULL columns" because the insert command is not adapted
else
adapter.Update(table); // it works (even on default value columns), but I don't get the identity
那么,如何在没有默认值的列上出现 NULL 值错误的情况下检索标识?通过摆脱来修改插入是不正确的 不允许 NULL 但具有默认值属性的每一列。
【问题讨论】:
【参考方案1】:这是一个sn-p:
USE AdventureWorks2012;
GO
--Display the value of LocationID in the last row in the table.
SELECT MAX(LocationID) FROM Production.Location;
GO
INSERT INTO Production.Location (Name, CostRate, Availability, ModifiedDate)
VALUES ('Damaged Goods', 5, 2.5, GETDATE());
GO
SELECT @@IDENTITY AS 'Identity';
GO
来自Microsoft docs。
【讨论】:
“如果语句触发一个或多个触发器执行插入生成标识值,则在语句返回触发器生成的最后一个标识值后立即调用@@IDENTITY。”那不是我想要的。此外,Select MAX(ID) 会因多个用户执行插入操作而产生不一致。以上是关于.Net SqlDataAdapter 在使用列上的默认值插入后检索身份的主要内容,如果未能解决你的问题,请参考以下文章
.Net SqlDataAdapter 和 SQL Server 中的触发器
如何用DataSet 和SqlDataAdapter读取SQL数据库中某列的多行数据?
ASP.NET + SqlDataAdapter 没有返回正确的查询结果
SqlDataAdapter.Fill 方法不会给出任何错误,但也不会返回任何数据以用于长时间运行的查询 ado.net core SQL Server