none
DBConcurrencyException RRS feed

Ответы

  • Смотри тут .
    • Помечено в качестве ответа Bahromjon 21 ноября 2010 г. 12:36
    12 ноября 2010 г. 5:08
    Модератор
  • Да, Начинаюшие сталкиваются такими "головоломками". С другой сторони это даже лучше. Мой ответ следуюший. (Уважаемые профессионали, если есть какие то недостатки прошу поправить, очен полезно будеть ссылки где можно подробне прочитать о DataAdapter + example).

    Допустим у нас есть таблица "Personal" (ACCESS). В программе есть OleDbDataAdapter adapter, DataTable table. В “Personal” есть две строки:

    ID

    Name

    1

    Sergey

    1

    Ivan

    Текст SelectCommand адаптера следуюшее:

    "Select * from [Personal]"

    Загружаем эту таблицу

    adapter.Fill(table);

    Текст DeleteCommand адаптера и параметр следуюшее:

    "Delete from [Personal] where [ID]=?"

    DeleteCommand.Parametr.Add("@[ID]", OleDbType.BigInt, 8, "ID").SourceVersion = DataRowVersion.Original;

    В программе удаляются строки

    table.Rows[0].Delete();/* == "Sergey"*/

    table.Rows[1].Delete(); /* == "Ivan"*/

    Следуюший код бросает DbConcurrencyException

    adapter.Update(table); //Exception

    Потому что DeleteCommand выполняется шаг за шаг каждому “Deleted” строку в table.Rows и при выполнении для первого же строку в базе удаляется все строки с ID=1 и будет возврашено резултат=2 А наш adapter будеть считат это нарушением параллелизма: «Должно быт удалено один строка, а в базе удаляется целых две, это нарушение параллелизма».

     

     

    • Помечено в качестве ответа Bahromjon 10 января 2011 г. 13:00
    12 ноября 2010 г. 5:43
  • DataAdapter спроектирован с рассчетом на то, что одной строке в запросе соответствует ровно одна строка в DataSet. И что операция над строкой в DataSet затрагивает ровно одну строку в базе.

    Предположим, проверки на количество затронутых строк нет (раз она мешает). В коде выше удаляем только одну строку:

    table.Rows[0].Delete();/* == "Sergey" *

    adapter.Update(table);

    В таблице остается строка Ivan. В базе ее уже нет. В таблице - все еще есть. Получается что DataAdapter удалил лишнюю строку.

    На самом деле проблема в отсутствии уникального ключа в таблице Personal. И в поиске записей для удаления по неуникальному полю. Команда Delete должна удалять конкретную запись, а не все что попало.

    Если ты идентифицируешь записи по полю ID, то  ID должне быть уникальным. Иначе ни DataAdapter, ты ты сам не сможешь ответить на вопрос - пользователь с ID 1 - это Сергей или Иван?

    • Помечено в качестве ответа Bahromjon 21 ноября 2010 г. 12:36
    12 ноября 2010 г. 14:02
    Модератор

Все ответы

  • Смотри тут .
    • Помечено в качестве ответа Bahromjon 21 ноября 2010 г. 12:36
    12 ноября 2010 г. 5:08
    Модератор
  • Да, Начинаюшие сталкиваются такими "головоломками". С другой сторони это даже лучше. Мой ответ следуюший. (Уважаемые профессионали, если есть какие то недостатки прошу поправить, очен полезно будеть ссылки где можно подробне прочитать о DataAdapter + example).

    Допустим у нас есть таблица "Personal" (ACCESS). В программе есть OleDbDataAdapter adapter, DataTable table. В “Personal” есть две строки:

    ID

    Name

    1

    Sergey

    1

    Ivan

    Текст SelectCommand адаптера следуюшее:

    "Select * from [Personal]"

    Загружаем эту таблицу

    adapter.Fill(table);

    Текст DeleteCommand адаптера и параметр следуюшее:

    "Delete from [Personal] where [ID]=?"

    DeleteCommand.Parametr.Add("@[ID]", OleDbType.BigInt, 8, "ID").SourceVersion = DataRowVersion.Original;

    В программе удаляются строки

    table.Rows[0].Delete();/* == "Sergey"*/

    table.Rows[1].Delete(); /* == "Ivan"*/

    Следуюший код бросает DbConcurrencyException

    adapter.Update(table); //Exception

    Потому что DeleteCommand выполняется шаг за шаг каждому “Deleted” строку в table.Rows и при выполнении для первого же строку в базе удаляется все строки с ID=1 и будет возврашено резултат=2 А наш adapter будеть считат это нарушением параллелизма: «Должно быт удалено один строка, а в базе удаляется целых две, это нарушение параллелизма».

     

     

    • Помечено в качестве ответа Bahromjon 10 января 2011 г. 13:00
    12 ноября 2010 г. 5:43
  • DataAdapter спроектирован с рассчетом на то, что одной строке в запросе соответствует ровно одна строка в DataSet. И что операция над строкой в DataSet затрагивает ровно одну строку в базе.

    Предположим, проверки на количество затронутых строк нет (раз она мешает). В коде выше удаляем только одну строку:

    table.Rows[0].Delete();/* == "Sergey" *

    adapter.Update(table);

    В таблице остается строка Ivan. В базе ее уже нет. В таблице - все еще есть. Получается что DataAdapter удалил лишнюю строку.

    На самом деле проблема в отсутствии уникального ключа в таблице Personal. И в поиске записей для удаления по неуникальному полю. Команда Delete должна удалять конкретную запись, а не все что попало.

    Если ты идентифицируешь записи по полю ID, то  ID должне быть уникальным. Иначе ни DataAdapter, ты ты сам не сможешь ответить на вопрос - пользователь с ID 1 - это Сергей или Иван?

    • Помечено в качестве ответа Bahromjon 21 ноября 2010 г. 12:36
    12 ноября 2010 г. 14:02
    Модератор