Проблема при получении столбца Identity ADO.net

У меня проблема с моим кодом, когда несколько пользователей работают одновременно. что он показывает мне ошибку:

«Идентификатор столбца» должен быть уникальным. Значение «9» уже присутствует.

Я попытался смоделировать это на небольшом коде, чтобы вы могли понять проблему.

предположим, что у нас есть база данных с одной таблицей с именем Table1

CREATE TABLE table1 (
[id] int not null IDENTITY(1,1) PRIMARY KEY,
[Name] nvarchar(max) not null,
);

и у меня есть это простое консольное приложение:

    static void Main(string[] args)
    {
        const string connectionString = "Server=.;Database=Test;User Id=sa;Password=;";
        using var connection = new SqlConnection(connectionString);

        connection.Open();

        using var adapter = new SqlDataAdapter("Select * from [Table1]", connection)
        {
            InsertCommand = new SqlCommand("Insert into Table1 ([Name]) values(@NameParam); Select [ID],[Name] from [Table1] where [id]= SCOPE_IDENTITY();",connection)
            {
                CommandType = CommandType.Text
            }
        };
        adapter.InsertCommand.Parameters.Add(new SqlParameter("@NameParam", SqlDbType.NVarChar, 40, "Name"));
        adapter.InsertCommand.UpdatedRowSource = UpdateRowSource.Both;

        // MissingSchemaAction adds any missing schema to 
        // the DataTable, including identity columns
        adapter.MissingSchemaAction = MissingSchemaAction.AddWithKey;

        adapter.RowUpdated += Adapter_RowUpdated;


        var table = new DataTable();

        adapter.Fill(table);


        // this insert command simulates another user on the network inserted a row 
        var anotherInsertCommand = new SqlCommand("Insert into Table1 ([Name]) values('Test1');",connection);
        anotherInsertCommand.ExecuteNonQuery();


        DataRow newRow = table.NewRow();
        newRow["Name"] = "test2";
        table.Rows.Add(newRow);

        DataRow newRow1 = table.NewRow();
        newRow1["Name"] = "test3";
        table.Rows.Add(newRow1);

        DataTable changedData = table.GetChanges();

        adapter.Update(changedData);

        table.Merge(changedData);


        table.AcceptChanges();


    }

    private static void Adapter_RowUpdated(object sender, SqlRowUpdatedEventArgs e)
    {
        // If this is an insert, then skip this row.
        if (e.StatementType != StatementType.Insert) return;
        if (e.Status == UpdateStatus.ErrorsOccurred)
        {
            // here it will show an error that the retrieved Identity column is already exist on the dataTable. Because we still didn't update the second row
            throw e.Errors;
        }
        e.Status = UpdateStatus.SkipCurrentRow;
    }

теперь проблема в том, что я заполняю свою таблицу данных при указании приложения, чтобы в таблице данных не было строк, а только схема.

а позже другой пользователь, использующий то же приложение, вставляет строку в базу данных. но мой dataTable не знал бы об этой строке.

после этого я вставляю две строки в свой dataTable и пытаюсь получить значения столбца Identity. но он показывает мне эту ошибку.

У кого-нибудь есть простой быстрый способ решить эту проблему. Например, отключить ограничения или что-то в этом роде. Я не знаю.

Примечание: способ получения значения Identity объясняется здесь, и я сделал так, как они объяснили. как получить значение идентификатора < /а>


person Shehab    schedule 19.04.2020    source источник
comment
Я попытался очистить ограничения, сделав это changeData.Constraints.Clear(); а затем позже вернуть их, и это сработало. но это правильный способ сделать это? Я не знаю, мне нужен твой совет   -  person Shehab    schedule 20.04.2020


Ответы (1)


  1. Возможным обходным путем может быть то, что вы используете, например. SELECT MAX(Id) FROM Table + 1, чтобы получить последний вставленный идентификатор перед вставкой. И в INSERT вы можете сделать

    SET IDENTITY_INSERT yourTable ON INSERT INTO yourTable (IdentityColumn, col2) VALUES (Identity, col2value ) SET IDENTITY_INSERT yourTable OFF

  2. Попробуйте установить свойство AutoIncrementSeed и AutoIncrementStep вашего столбца identy в DataTable на -1.

Вот документация, в которой они говорят: вы можете создать новую строку, используя свойство ItemArray класса DataRow и передав массив значений. Это потенциальная проблема для столбца, для которого для параметра AutoIncrement установлено значение true. Я знаю, что вы не используете ItemArray, но, возможно, вы имеете дело с чем-то подобным.

person Samuel B.    schedule 19.04.2020
comment
Привет, спасибо за ответ. код, который я предоставил, это не весь мой фактический код. Я просто смоделировал то, что на самом деле происходит со мной. Я не могу выбрать максимальное значение, потому что это повлияет на производительность. проблема появляется, когда несколько пользователей работают одновременно. но если работает только один пользователь, все идет нормально. проблема, я думаю, заключается в том, что dataAdapter пытается обновить DataTable полученным значением. он показывает эту ошибку, потому что вторая строка данных имеет такое же полученное значение идентификатора для первой строки. - person Shehab; 19.04.2020
comment
@Shebab, если вы установите AutoIncrement=false; IdentityColumn Это не помогло? - person Samuel B.; 20.04.2020