【问题标题】:An Issue when retrieving Identity column ADO.net检索身份列 ADO.net 时出现问题
【发布时间】:2020-04-19 16:36:13
【问题描述】:

当多个用户同时工作时,我的代码出现问题。它向我显示了一个错误:

'列'id'被限制为唯一。值“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 值的方式,我按照他们的解释做了。 how to retrieve Identity value

【问题讨论】:

  • 我试图通过这个 changedData.Constraints.Clear(); 清除约束然后返回它们并且它起作用了。但这是正确的方法吗?我不知道我需要你的建议

标签: c# sql-server ado.net ado sqldataadapter


【解决方案1】:
  1. 您可以使用可能的解决方法,例如SELECT MAX(Id) FROM Table + 1 在插入之前获取最后插入的 ID。而在 INSERT 你可以做

    SET IDENTITY_INSERT yourTable ON 插入您的表格 (身份列,col2) 价值观 (身份,col2value) SET IDENTITY_INSERT yourTable 关闭

  2. 尝试将DataTable中身份列的AutoIncrementSeed和AutoIncrementStep属性设置为-1。

Here 是他们在其中说的文档:“您可以使用 DataRow 类的 ItemArray 属性并传入一个值数组来创建一个新行。对于 AutoIncrement 设置为的列来说,这是一个潜在问题是的。“我知道你没有使用 ItemArray 但也许你正在处理类似的事情。

【讨论】:

  • 您好,感谢您的回复。我提供的代码并不是我所有的实际代码。我只是模拟了我实际发生的事情。我无法选择最大值,因为这会影响性能。当多个用户同时工作时会出现此问题。但如果只有一个用户在工作,一切都会好起来的。我认为的问题是当 dataAdapter 尝试使用检索到的值更新 DataTable 时。它显示此错误是因为第二个 dataRow 具有与第一行相同的检索标识值。
  • @Shebab 如果你设置 AutoIncrement=false; IdentityColumn 没有帮助?
猜你喜欢
  • 2020-05-16
  • 2018-10-25
  • 1970-01-01
  • 2021-08-03
  • 1970-01-01
  • 2011-03-12
  • 2023-04-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多