ChangeConflictException при обновлении строк с помощью LINQ-to-SQL - PullRequest
2 голосов
/ 30 октября 2011

У меня есть форма, которая содержит сетку данных и кнопку сохранения.

Когда пользователь нажимает кнопку сохранения, я проверяю наличие новых строк, проверяя определенный столбец. Если его значение равно 0, я вставляю строку в базу данных, а если значение столбца не равно 0, я обновляю эту строку.

Я могу вставить правильно, но при обновлении возникает исключение:

Исключение ChangeConflictException не обработано, 1 из 6 обновлений не удалось.

Я проверил оператор обновления и уверен, что он правильный. В чем проблема, кто-нибудь может мне помочь?

int id;
for (int i = 0; i < dgvInstructores.Rows.Count - 1; i++)
{
    id = int.Parse(dgvInstructores.Rows[i].Cells["ID"].Value.toString());
    if (id == 0)
    {
        dataClass.procInsertInstructores(name, nationalNum, tel1, tel2, 
                                            address, email);
        dataClass.SubmitChanges();
    }
    else
    {
        dataClass.procUpdateInstructores(id, name, nationalNum, tel1, tel2, 
                                            address, email);
        dataClass.SubmitChanges();
    }
}

Я использую linq для запроса базы данных sql server2005 и vs2008

хранимая процедура для 'procUpdateInstructores':

set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
go

ALTER proc [dbo].[procUpdateInstructores]
@ID int,
@name varchar(255),
@NationalNum varchar(25),
@tel1 varchar(15),
@tel2 varchar(15),
@address varchar(255),
@email varchar(255)
as
begin

BEGIN TRANSACTION

update dbo.Instructores
set
Name = @name , NationalNum = @NationalNum ,
tel1 = @tel1 , tel2 = @tel2 , address = @address , email = @email
where ID = @ID

IF (@@ROWCOUNT > 0) AND (@@ERROR = 0)
     BEGIN
          COMMIT TRANSACTION
     END
ELSE
     BEGIN
          ROLLBACK TRANSACTION
     END
end

Ответы [ 3 ]

0 голосов
/ 30 октября 2011

По своему опыту, (работая с формами .net и mvc с linq-to-sql) я обнаружил, что несколько раз, если коллекция форм содержит параметр ID объекта данных, обновление наверняка завершится неудачей.

Даже если идентификатор является фактическим идентификатором, он все равно помечается как 'propertyChanged', когда вы связываете его, обновляете или назначаете другой переменной.

Как таковой мы можем увидеть код для ваших сохраненных процедур? Точнее, обновление proc?

Код, который вы разместили выше, в порядке, исключение должно исходить из вашего сохраненного процесса.

Однако, если вы уверены, что процедура верна, возможно, посмотрите на HTML-код, используемый для генерации таблицы. Некоторые ошибки могут присутствовать в отношении 0/1 в столбцах идентификаторов и т. Д.

0 голосов
/ 31 октября 2011

В этом случае оказывается, что вы используете DataGridView (то есть WinForms).Я также предполагаю, что ваш dataClass сохраняется в форме, так что вы загрузили и привязали DataGridView из того же dataClass, в котором вы пытаетесь сохранить изменения в этом примере.

Предполагается, что вы связываете DataGridView с сущностямивозвращается через LINQ to SQL, когда вы редактируете значения, вы отмечаете нужную сущность, которую необходимо обновить при вызове следующего SubmitChanges.

В вашем обновлении вы вызываете dataClass.procUpdateInstructores(id, name, nationalNum, tel1, tel2, address, email);, которыйнемедленно выдает хранимую процедуру для базы данных, устанавливая новые значения по мере их редактирования.Следующая строка - кикер.Поскольку ваш контекст данных все еще думает, что объект все еще грязный, SubmitChanges пытается отправить другой оператор обновления в вашу базу данных с исходными значениями, которые он извлек в качестве части предложения Where (для проверки на параллелизм).Поскольку хранимый процесс обновил эти значения, предложение Where не может найти подходящее значение и, таким образом, возвращает исключение параллелизма.

В этом случае лучше всего изменить модель LINQ to SQL, чтобы использовать ваши хранимые процедуры.для обновлений и вставок, а не версий, сгенерированных во время выполнения.Затем в своем коде синтаксического анализа просто вызовите SubmitChanges, не вызывая procUpdateInstructores вручную.Если ваш dbml настроен правильно, он будет вызывать хранимый процесс, а не оператор динамического обновления.

Кроме того, FWIW, ваш сохраненный процесс, кажется, не делает ничего больше, чем сгенерированный SQL.На самом деле, LINQ to SQL даст вам больше функциональности, так как вы все равно не проверяете параллелизм в своем хранимом процессе.Если вам необходимо использовать хранимые протоколы вашим администратором базы данных или какой-либо политикой безопасности, вы можете сохранить их, но вы можете рассмотреть возможность их обхода, если это все, что делают ваши хранимые процессы, и полагаться на сгенерированный SQL времени выполнения обновлений.

0 голосов
/ 30 октября 2011

При отсутствии дополнительной информации (как выглядит ваш код обновления SQL или C # ...) моей первой рекомендацией было бы сделать SubmitChanges один раз, вне цикла for, а не отправлять изменения один раз в строку.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...