【问题标题】:Violation of PRIMARY KEY constraint . Cannot insert duplicate key in object - ADO.NET违反 PRIMARY KEY 约束。无法在对象中插入重复键 - ADO.NET
【发布时间】:2016-06-07 21:23:06
【问题描述】:

我正在尝试插入一个新人的数据,我可以在第一次尝试时,但在第二次尝试时会出现违反主键的错误,事实上,每次都会增加人员 ID (personId)正在尝试添加一个新人,所以我意识到错误是主键

餐桌人

CREATE TABLE [dbo].[Person] (
    [personID]    INT NOT NULL,
    [personName] VARCHAR (50) NOT NULL,
    PRIMARY KEY CLUSTERED ([personID] ASC)
);

创建和插入新人物的方法

protected void BtnCreate(object sender, EventArgs e)
    {
      SqlConnection connection = new SqlConnection(connectionString);
      //id to new person
      int id = 0;
      //command
      string command = "INSERT INTO [Person] ([personID], [personName]) VALUES (@id, @name)";

      SqlCommand cmd = new SqlCommand(command, connection);
      cmd.Parameters.AddWithValue("@id", id++);//id increase
      cmd.Parameters.AddWithValue("@name", name.Text);
      connection.Open();
      cmd.ExecuteNonQuery();
      connection.Close();
    }

有什么建议吗?

【问题讨论】:

  • 转到您的数据库架构并更改 personID 列,添加 IDENTITY 属性。然后删除任何为自己设置 personID 值的尝试

标签: c# sql-server


【解决方案1】:

您当前的代码无法再次运行,因为您递增的 id 变量是分配在堆栈上的局部变量。当方法退出时,堆栈上的所有内容都会被清除。再次单击按钮,您重新进入该方法,但变量被重置为零,并且您的增量再次将变量设置为 1。因此 personID 字段的重复异常。

我建议更改您的 personID 列,添加 IDENTITY 属性。
通过这种方式,数据库自己计算下一个值以分配给personID 字段,并且您不需要记住分配给表的最后一个 id 是什么(这实际上是不可能在多用户中以安全的方式实现的环境)

添加 IDENTITY 属性后,您可以将数据库分配的值读回personID 字段,将查询更改为

string command = @"INSERT INTO [Person] ([personName]) 
                   OUTPUT INSERTED.personID
                   VALUES (@name)";

并使用 ExecuteScalar 运行查询

  int id = Convert.ToInt32(cmd.ExecuteScalar());

【讨论】:

    【解决方案2】:

    如果您不关心 personID 字段的实际值(您的代码似乎表明了这一点)。并且,只希望它是唯一的并以 1 递增。

    为了说明@Steve 所指出的,您可以这样定义您的表:(在 T-SQL 中)

    CREATE TABLE [dbo].[Person] (
    [personID] [int] IDENTITY(1,1) NOT NULL,
    [personName] VARCHAR (50) NOT NULL,
        PRIMARY KEY CLUSTERED ([personID] ASC)
    );
    

    这将消除您插入 personID 的需要

    protected void BtnCreate(object sender, EventArgs e)
        {
          SqlConnection connection = new SqlConnection(connectionString);
    
          //command
          string command = "INSERT INTO [Person] ([personName]) VALUES (@name)";
    
          SqlCommand cmd = new SqlCommand(command, connection);
          cmd.Parameters.AddWithValue("@name", name.Text);
          connection.Open();
          cmd.ExecuteNonQuery();
          connection.Close();
        }
    

    【讨论】:

      【解决方案3】:

      谢谢大家,你们所有的答案都是正确的,但我为我的情况找到了一个更好的解决方案,我将 id 用作一个静态值,至少初始化一个并停止运行,它没有错误并且按我想要的方式工作我感谢您的时间和时间

      我的表不需要使用身份,因为我打算在您每次单击按钮创建新人时输入 ID 增量

      CREATE TABLE [dbo].[Person] (
          [personID]    INT NOT NULL,
          [personName] VARCHAR (50) NOT NULL,
          PRIMARY KEY CLUSTERED ([personID] ASC)
      );
      

      我使用了static int id = -1,但它无法正常工作

      //id to new person
      private static int id = -1;
      
      protected void BtnCreate(object sender, EventArgs e)
          {
            SqlConnection connection = new SqlConnection(connectionString);
      
            //command
            string command = "INSERT INTO [Person] ([personID], [personName]) VALUES (@id, @name)";
      
            SqlCommand cmd = new SqlCommand(command, connection);
            cmd.Parameters.AddWithValue("@id", id++);//id increase
            cmd.Parameters.AddWithValue("@name", name.Text);
            connection.Open();
            cmd.ExecuteNonQuery();
            connection.Close();
          }
      

      【讨论】:

        【解决方案4】:

        史蒂夫有一个很好的答案,或者如果不能重新安排你的数据库架构,那么你可以这样做:

        protected void BtnCreate(object sender, EventArgs e)
        {
          SqlConnection connection = new SqlConnection(connectionString);
        
          connection.Open();
        
          SqlCommand idcommand = new SqlCommand("select max([personID]) from Person", connection)
          //id to new person
          int id = ((int)idcommand.ExecuteScalar()) + 1;
          //command
          string command = "INSERT INTO [Person] ([personID], [personName]) VALUES (@id, @name)";
        
          SqlCommand cmd = new SqlCommand(command, connection);
          cmd.Parameters.AddWithValue("@id", id++);//id increase
          cmd.Parameters.AddWithValue("@name", name.Text);
          cmd.ExecuteNonQuery();
          connection.Close();
        }
        

        【讨论】:

        • 我不会推荐这个。 MAX 的问题是当您有多个插入记录的用户时。迟早你会得到一个错误,因为 MAX 可能会向多个用户返回相同的值。另一个(次要)问题是这样一个事实,即您以这种方式访问​​数据库两次,这可能会影响性能。
        • 我也不推荐它,这是作为 alternative 发布的 - 在某些遗留情况下,您无法更改数据库架构。跨度>
        猜你喜欢
        • 2013-05-16
        • 1970-01-01
        • 1970-01-01
        • 2014-06-30
        • 1970-01-01
        • 2020-03-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多