.Net SqlDataAdapter получает идентификатор после вставки со значением по умолчанию в столбце

Мне нужен способ получить значение идентификатора после вставки с помощью SqlDataAdapter.

Я проверил следующие случаи:

  1. Если я запускаю select @@ identity после вставки, возвращаемое значение неверно, если есть другие триггеры, выполняющие вставки.

  2. Если я запускаю select scope_identity () ПОСЛЕ вставки, это не тот же пакет, поэтому идентификатор равен нулю

  3. Решением было запустить select scope_identity () в том же пакете, поэтому я изменил 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 не допускает значений NULL, но имеет значение по умолчанию 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, но имеет свойство значения по умолчанию.


person Andrei94    schedule 09.07.2018    source источник


Ответы (1)


вот отрывок:

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 документы.

person Barr J    schedule 09.07.2018
comment
Если оператор запускает один или несколько триггеров, которые выполняют вставки, которые генерируют значения идентификаторов, вызов @@ IDENTITY сразу после оператора возвращает последнее значение идентификатора, сгенерированное триггерами. это не то, что я хочу. Кроме того, Select MAX (ID) вызовет несогласованность из-за того, что несколько пользователей выполняют вставки. - person Andrei94; 09.07.2018