重复键值违反唯一约束(主键)

duplicate key value violates unique constraint (primary key)

您好,我这里有一个程序可以将选中列表框中的选中值存储到数据库中。问题是我总是遇到一个异常,说 "duplicate key value violates unique constraint pk_famcon." 我已经尝试过其他替代方法,但它总是会以这种方式结束。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Npgsql;

namespace WindowsFormsApplication1
{
    public partial class Form8 : Form
    {
        public Form8()
        {
            InitializeComponent();
            this.Load += Form8_Load;
            button1.Click += button1_Click;
        }

            DataSet ds = new DataSet();

        private void Form8_Load(object sender, EventArgs e)
        {
            Populate_DataSet();
            FillCheckListBox();
        }

        private void Populate_DataSet()
        {
            string connstring = "Server=localhost;Port=5432;User Id=postgres;Password=021393;Database=postgres;";
            using (NpgsqlConnection conn = new NpgsqlConnection(connstring))
            {
                string conditionName = "SELECT * FROM condition";
                NpgsqlDataAdapter da = new NpgsqlDataAdapter(conditionName, conn);
                da.Fill(ds, "conname");
                da.Fill(ds, "conid");
            }
        }

        private void FillCheckListBox()
        {
            DataRow row1 = null;
            int iRowCnt = 0;

            checkedListBox1.Items.Clear();

            foreach (DataRow row_1 in ds.Tables["conname"].Rows)
            {
                row1 = row_1;
                checkedListBox1.Items.Add(ds.Tables["conname"].Rows[iRowCnt][1]);
                iRowCnt = iRowCnt + 1;     
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            MessageBox.Show("Data has been saved");
          if (checkedListBox1.Items.Count > 0)
          {
              string connstring = ("Server=localhost;Port=5432;User Id=postgres;Password=021393;Database=postgres;");
              NpgsqlConnection conn = new NpgsqlConnection(connstring);
              conn.Open();

              for (int i = 0; i <= checkedListBox1.CheckedItems.Count - 1; i++)
              {
                  NpgsqlCommand cmd = new NpgsqlCommand("Insert into famhistory(famcon) Values (@famcon)", conn);
                  cmd.Parameters.AddWithValue("@famcon", checkedListBox1.Text);
                  cmd.ExecuteNonQuery();
                  string value = checkedListBox1.CheckedItems[i].ToString(); 
              }
              MessageBox.Show("Data has been saved");
              conn.Close();
          }

        }
    }
}

看看这个循环:

for (int i = 0; i <= checkedListBox1.CheckedItems.Count - 1; i++)
{
    NpgsqlCommand cmd = new NpgsqlCommand("Insert into famhistory(famcon) Values (@famcon)", conn);
    cmd.Parameters.AddWithValue("@famcon", checkedListBox1.Text);
    cmd.ExecuteNonQuery();
    string value = checkedListBox1.CheckedItems[i].ToString(); 
}

您在循环的每次迭代中都将相同的值 (checkedListBox1.Text) 插入到主键字段中,听上去是这样。在最后一条语句之前,您不会使用 i (循环中的索引) - 这只是声明并为立即超出范围的局部变量赋值。我怀疑你的意思是:

for (int i = 0; i <= checkedListBox1.CheckedItems.Count - 1; i++)
{
    NpgsqlCommand cmd = new NpgsqlCommand("Insert into famhistory(famcon) Values (@famcon)", conn);
    string value = checkedListBox1.CheckedItems[i].ToString(); 
    cmd.Parameters.AddWithValue("@famcon", value);
    cmd.ExecuteNonQuery();
}

除此之外,还有一些值得改变的地方:

  • 循环条件更常规地写为:

    for (int i = 0; i < checkedListBox1.CheckedItems.Count; i++)

...或使用 foreach 循环。

  • 你应该每次都使用using语句来处理你的命令
  • 明确指定参数类型,然后使用 Value 属性
  • 设置参数值通常更清晰

把这些放在一起,你有:

foreach (var item in checkedListBox1.CheckedItems)
{
    using (var cmd = new NpgsqlCommand("Insert into famhistory(famcon) Values (@famcon)", conn)
    {
        cmd.Parameters.Add("@famcon", NpgsqlDbType.Varchar).Value = item.ToString();
        cmd.ExecuteNonQuery();
    }
}