.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对象

SqlDataAdapter.Fill 方法不会给出任何错误,但也不会返回任何数据以用于长时间运行的查询 ado.net core SQL Server

SqlDataAdapter.Fill - 异步方法