Исключение DBConcurrencyException в базе данных SQL

#c# #sql #database

#c# #sql #База данных

Вопрос:

Он все,

Недавно я запустил проект, которому требуется много данных. На самом деле так много, что это не может быть сохранено в памяти среды выполнения. Я искал решения этой проблемы и выбрал для использования базы данных SQL. Я нашел руководство, объясняющее, как они работают, и воссоздал его сам. Это гарантирует синхронизацию вашей физической базы данных и виртуального набора данных с помощью DataAdapter для обновления базы данных;

(К вашему сведению, руководство можно найти здесь:http://www.homeandlearn.co.uk/csharp/csharp_s12p1.html );

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

Когда я запускаю программу, все функциональные возможности работают, я могу добавлять строку и удалять строку. Но когда я пытаюсь выполнить оба в одном и том же исполнении (order = добавить, затем удалить), появляется ошибка. В нем описывается, что команда DeleteCommand затронула ноль из одной ожидаемой записи.

Я использовал следующие фрагменты кода:

Инициализация:

 private void Form1_Load(object sender, EventArgs e)
        {
            con = new SqlConnection();
            ds1 = new DataSet();

            con.ConnectionString = "Data Source=.\SQLEXPRESS;AttachDbFilename=C:\<Private>\MyWorkers.mdf;Integrated Security=True;Connect Timeout=30;User Instance=True";

            con.Open();

            string sql = "SELECT * From tblWorkers";
            da = new SqlDataAdapter(sql, con);

            da.Fill(ds1, "Workers");
            NavigateRecords();

            MaxRows = ds1.Tables["Workers"].Rows.Count;
            updateIndicator();

            con.Close();
            //con.Dispose();
        }
  

(Примечание: Я закомментировал каталог по соображениям конфиденциальности);

Добавление строки выполняется следующим образом:

 private void btnSave_Click(object sender, EventArgs e)
        {
            SqlCommandBuilder cb = new SqlCommandBuilder(da);

            DataRow dRow = ds1.Tables["Workers"].NewRow();

            dRow[1] = textBox1.Text;
            dRow[2] = textBox2.Text;
            dRow[3] = textBox3.Text;

            ds1.Tables["Workers"].Rows.Add(dRow);

            MaxRows = MaxRows   1;
            inc = MaxRows - 1;

            da.Update(ds1, "Workers");

            MessageBox.Show("Entry Added");
        }
  

При удалении строки выполняется этот код:

 private void btnDelete_Click(object sender, EventArgs e)
        {
            SqlCommandBuilder cb = new SqlCommandBuilder(da);

            ds1.Tables["Workers"].Rows[inc].Delete();
            MaxRows--;
            inc = 0;
            NavigateRecords();

            da.Update(ds1, "Workers");

            MessageBox.Show("Record Deleted");
        }
  

Методы NavigateRecord() и setIndicator() не имеют отношения к этому вопросу, поскольку они являются элементами GUI.

Заранее всем спасибо!

Комментарии:

1. Как вы пытаетесь выполнить их оба одновременно? Я предполагаю, что ваша функция add завершается с ошибкой, а затем delete выдает эту ошибку.

2. Это не кажется хорошей идеей. Почему вы удаляете запись, основанную на статической переменной, указывающей индекс записи в datatable ( inc )? Что произойдет, если кто-то добавит две записи подряд перед нажатием кнопки удаления?

Ответ №1:

Я наткнулся на это вопрос заявление при поиске способа предотвратить блокировку SQL Server всей записи (я хочу, чтобы она блокировалась по значению поля / столбца вместо этого) и заметил, что ответа не было дано, так что держи, если кто-нибудь еще столкнется с этой проблемой:

OP на самом деле не задавал вопрос, а только указал, в чем проблема; итак, вот ответ на вопрос, который не был задан «Как мне предотвратить нарушения параллелизма базы данных?»:

Нарушения параллелизма базы данных (в данном случае) можно предотвратить, приняв решение о том, какие данные должны поступать в базу данных. Большинство людей выбирают подход, который «последний в wins». Итак, при обработке операций с использованием TableAdapter поместите обновление в Try / Catch и во время Catch для исключения DBConcurrencyException просто убедитесь, что вы выполнили быстрое заполнение, затем измените все, что вы должны были изменить, а затем выполните обновление. Срабатывает каждый раз.