повторяющееся значение ключа нарушает уникальное ограничение (первичный ключ)

Привет, у меня есть программа, которая хранит проверенные значения в checklistbox в базе данных. Проблема в том, что я всегда сталкиваюсь с исключением, в котором говорится, что «повторяющееся значение ключа нарушает уникальное ограничение 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();
          }

        }
    }
}

person s_tee    schedule 28.07.2015    source источник
comment
мне нужно использовать для этого внешний ключ?   -  person s_tee    schedule 28.07.2015


Ответы (1)


Посмотрите на этот цикл:

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();
    }
}
person Jon Skeet    schedule 28.07.2015
comment
@s_tee Если ответ вам поможет, примите его. Я посетил ваш профиль, вы не приняли ни одного из полученных ответов. - person Shaharyar; 28.07.2015