Проблема при получении идентификатора столбца ADO.net - PullRequest
0 голосов
/ 19 апреля 2020

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

'Идентификатор столбца' должен быть уникальным. Значение '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 не знал бы об этой строке.

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

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

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

1 Ответ

0 голосов
/ 19 апреля 2020
  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 для вашего столбца идентификаторов в DataTable равно -1.

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

...