ChangeConflictException в Linq для обновления Sql - PullRequest
15 голосов
/ 19 марта 2009

Я нахожусь в мире боли с этим, и я был бы очень признателен, если бы кто-то мог помочь.

У меня есть DataContext, прикрепленный к одной тестовой таблице в базе данных. Тестовая таблица выглядит следующим образом:

CREATE TABLE [dbo].[LinqTests](
    [ID] [bigint] IDENTITY(1,1) NOT NULL,
    [StringValue] [varchar](255) NOT NULL,
    [DateTimeValue] [datetime] NOT NULL,
    [BooleanValue] [bit] NOT NULL,
    CONSTRAINT [PK_LinqTests] PRIMARY KEY CLUSTERED ([ID] ASC))
ON [PRIMARY]

Используя Linq, я могу добавлять, извлекать и удалять строки из тестовой таблицы, но не могу обновить строку - для ОБНОВЛЕНИЯ я всегда получаю ChangeConflictException с пустой коллекцией ObjectChangeConflict.MemberConflicts. Вот используемый код:

var dataContext = new UniversityDataContext();
dataContext.Log = Console.Out;

for (int i = 1; i <= 1; i++) {
    var linqTest = dataContext.LinqTests.Where(l => (l.ID == i)).FirstOrDefault();

    if (null != linqTest) {
        linqTest.StringValue += " I've been updated.";
    }
    else {
        linqTest = new LinqTest {
            BooleanValue = false,
            DateTimeValue = DateTime.UtcNow,
            StringValue = "I am in loop " + i + "."
        };
        dataContext.LinqTests.InsertOnSubmit(linqTest);
    }
}

try {
    dataContext.SubmitChanges(ConflictMode.ContinueOnConflict);
}
catch (ChangeConflictException exception) {
    Console.WriteLine("Optimistic concurrency error.");
    Console.WriteLine(exception.Message);
    Console.ReadLine();
}

Console.ReadLine();

Вот вывод журнала для обновления, выполненного через DataContext.

UPDATE [dbo].[LinqTests]
SET [StringValue] = @p3
WHERE ([ID] = @p0) AND ([StringValue] = @p1) AND ([DateTimeValue] = @p2) AND (NOT ([BooleanValue] = 1))
-- @p0: Input BigInt (Size = 0; Prec = 0; Scale = 0) [1]
-- @p1: Input VarChar (Size = 15; Prec = 0; Scale = 0) [I am in loop 1.]
-- @p2: Input DateTime (Size = 0; Prec = 0; Scale = 0) [3/19/2009 7:54:26 PM]
-- @p3: Input VarChar (Size = 34; Prec = 0; Scale = 0) [I am in loop 1. I've been updated.]
-- Context: SqlProvider(Sql2000) Model: AttributedMetaModel Build: 3.5.30729.1

Я выполняю этот запрос на кластерном SQL Server 2000 (8.0.2039). Я не могу понять, что происходит здесь. Выполнение аналогичного запроса UPDATE для БД, похоже, работает нормально.

Заранее спасибо за любую помощь.

Ответы [ 4 ]

28 голосов
/ 16 апреля 2009

Я наконец понял, что происходит с этим. По-видимому, для этого сервера была включена опция «без счета».

В Microsoft SQL Server Management Studio 2005:

  1. Щелкните правой кнопкой мыши на сервере и выберите Свойства
  2. В левой части окна Свойства сервера выберите Соединения Страница
  3. В разделе Параметры подключения по умолчанию убедитесь, что "no count" не выбран.

По-видимому, LINQ to SQL использует @@ ROWCOUNT после обновлений для создания автоматической оптимистической проверки параллелизма. Конечно, если для всего сервера включено «no count», @@ ROWCOUNT всегда возвращает ноль, а LINQ to SQL генерирует исключение ConcurrencyException после выпуска обновлений для базы данных.

Это не единственное поведение обновления, которое использует LINQ to SQL. LINQ to SQL не выполняет автоматическую оптимистическую проверку параллелизма с помощью @@ ROWCOUNT, если в вашей таблице есть столбец TIMESTAMP.

1 голос
/ 02 февраля 2012

У меня была такая же проблема с SQL Server 2008, и параметр подключения no count уже превратился в .

Вместо того, чтобы изменять свойство Update Check на Никогда (как предлагает Квинтин), я установил его на WhenChanged и проблема была решена.

1 голос
/ 19 марта 2009

Возможно ли, что какие-либо данные для строки изменились между моментом их получения и попыткой обновления? Потому что LINQ-> SQL имеет автоматическую проверку параллелизма, которая проверит содержимое объекта по текущим сохраненным значениям (как вы видите в сгенерированном запросе). Если возможно, что какое-либо из полей изменилось для строки в БД по сравнению с объектом, который отслеживает LINQ, то обновление завершится неудачно. Если это происходит и по понятной причине, и вы знаете, какие поля, вы можете обновить объект в конструкторе DBML; выберите поле по причине и измените свойство «Проверка обновления» на «Никогда».

0 голосов
/ 29 августа 2015

Сначала запишите подробности о проблеме, какая строка и какое поле конфликтуют и какие значения конфликтуют.

Чтобы реализовать такой подробный журнал, см. Мое решение здесь:

Что я могу сделать, чтобы разрешить исключение «Строка не найдена или изменена» в LINQ to SQL в базе данных SQL Server Compact Edition?

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