При выполнении SubmitChanges в DataContext после обновления пары свойств с помощью соединения LINQ to SQL (для SQL Server Compact Edition) я получаю сообщение «Строка не найдена или не изменена». ChangeConflictException.
var ctx = new Data.MobileServerDataDataContext(Common.DatabasePath);
var deviceSessionRecord = ctx.Sessions.First(sess => sess.SessionRecId == args.DeviceSessionId);
deviceSessionRecord.IsActive = false;
deviceSessionRecord.Disconnected = DateTime.Now;
ctx.SubmitChanges();
Запрос генерирует следующий SQL:
UPDATE [Sessions]
SET [Is_Active] = @p0, [Disconnected] = @p1
WHERE 0 = 1
-- @p0: Input Boolean (Size = 0; Prec = 0; Scale = 0) [False]
-- @p1: Input DateTime (Size = 0; Prec = 0; Scale = 0) [9/4/2008 5:12:02 PM]
-- Context: SqlProvider(SqlCE) Model: AttributedMetaModel Build: 3.5.21022.8
Очевидной проблемой является WHERE 0 = 1. После загрузки записи я подтвердил, что все свойства в "deviceSessionRecord" верны для включения первичного ключа. Также при перехвате исключения «ChangeConflictException» нет дополнительной информации о том, почему это не удалось. Я также подтвердил, что это исключение генерируется только с одной записью в базе данных (запись, которую я пытаюсь обновить)
Странно то, что у меня есть очень похожий оператор обновления в другом разделе кода, который генерирует следующий SQL и действительно обновляет мою базу данных SQL Server Compact Edition.
UPDATE [Sessions]
SET [Is_Active] = @p4, [Disconnected] = @p5
WHERE ([Session_RecId] = @p0) AND ([App_RecId] = @p1) AND ([Is_Active] = 1) AND ([Established] = @p2) AND ([Disconnected] IS NULL) AND ([Member_Id] IS NULL) AND ([Company_Id] IS NULL) AND ([Site] IS NULL) AND (NOT ([Is_Device] = 1)) AND ([Machine_Name] = @p3)
-- @p0: Input Guid (Size = 0; Prec = 0; Scale = 0) [0fbbee53-cf4c-4643-9045-e0a284ad131b]
-- @p1: Input Guid (Size = 0; Prec = 0; Scale = 0) [7a174954-dd18-406e-833d-8da650207d3d]
-- @p2: Input DateTime (Size = 0; Prec = 0; Scale = 0) [9/4/2008 5:20:50 PM]
-- @p3: Input String (Size = 0; Prec = 0; Scale = 0) [CWMOBILEDEV]
-- @p4: Input Boolean (Size = 0; Prec = 0; Scale = 0) [False]
-- @p5: Input DateTime (Size = 0; Prec = 0; Scale = 0) [9/4/2008 5:20:52 PM]
-- Context: SqlProvider(SqlCE) Model: AttributedMetaModel Build: 3.5.21022.8
Я подтвердил, что правильные значения первичных полей были определены как в схеме базы данных, так и в DBML, который генерирует классы LINQ.
Думаю, это почти вопрос из двух частей:
- Почему выбрасывается исключение?
- После просмотра второго набора сгенерированных SQL кажется, что для обнаружения конфликтов было бы неплохо проверить все поля, но я полагаю, что это было бы довольно неэффективно. Это всегда так работает? Есть ли возможность просто проверить первичный ключ?
Я боролся с этим последние два часа, поэтому любая помощь будет оценена.
источник
Ответы:
Противно, но просто:
Убедитесь, что типы данных для всех полей в O / R-Designer соответствуют типам данных в вашей таблице SQL. Дважды проверьте наличие значения NULL! Столбец должен быть либо допускающим значение NULL в O / R-Designer и SQL, либо не допускать значения NULL в обоих.
Например, «заголовок» столбца NVARCHAR помечен в вашей базе данных как NULLable и содержит значение NULL. Несмотря на то, что столбец отмечен как NOT NULLable в вашем сопоставлении O / R, LINQ успешно загрузит его и установит для String-String значение null.
Тот же симптом появится, когда типы данных поля не соответствуют типу данных в SQL или если поля отсутствуют, поскольку LINQ не сможет гарантировать, что данные SQL не изменились с момента чтения данных.
источник
VARCHAR(MAX) NOT NULL
наVARCHAR(MAX) NULL
и ожидая, что оно будет работать. Очень простая ошибка.NUMERIC(12,8)
столбец, сопоставленный соDecimal
свойством. Мне пришлось уточнить DbType в атрибуте Column[Column(DbType="numeric(12,8)")] public decimal? MyProperty ...
Во-первых, полезно знать, что вызывает проблему. Решение с поиском в Google должно помочь, вы можете зарегистрировать детали (таблица, столбец, старое значение, новое значение) о конфликте, чтобы найти лучшее решение для разрешения конфликта позже:
Создайте помощника для упаковки вашего sumbitChanges:
А затем вызовите код отправки изменений:
Наконец, зарегистрируйте исключение в вашем глобальном обработчике исключений:
источник
В DataContext есть метод Refresh, который может здесь помочь. Он позволяет перезагружать запись базы данных перед отправкой изменений и предлагает различные режимы для определения, какие значения следует сохранить. «KeepChanges» кажется мне самым умным для моих целей, он предназначен для объединения моих изменений с любыми неконфликтными изменениями, которые произошли в базе данных за это время.
Если я правильно понимаю. :)
источник
dc.Refresh(RefreshMode.KeepChanges,changedObject);
устранил проблему в моем случае: до dc.SubmitChangesЭто также может быть вызвано использованием более одного контекста DbContext.
Так например:
Этот код будет время от времени давать сбой, что кажется непредсказуемым, поскольку пользователь используется в обоих контекстах, изменяется и сохраняется в одном, а затем сохраняется в другом. Представление в памяти пользователя, владеющего «Something», не соответствует тому, что находится в базе данных, и поэтому вы получаете эту скрытую ошибку.
Один из способов предотвратить это - написать любой код, который может когда-либо вызываться как библиотечный метод, таким образом, чтобы он принимал необязательный DbContext:
Итак, теперь ваш метод принимает необязательную базу данных, а если ее нет, он сам создает ее. Если есть, он просто повторно использует то, что было передано. Вспомогательный метод позволяет легко повторно использовать этот шаблон в вашем приложении.
источник
Я решил эту ошибку, перетащив таблицу из проводника сервера в конструктор и перестроив ее.
источник
Вот что вам нужно, чтобы переопределить эту ошибку в коде C #:
источник
Я не знаю, нашли ли вы какие-либо удовлетворительные ответы на свой вопрос, но я разместил аналогичный вопрос и в конце концов ответил на него сам. Оказалось, что для базы данных была включена опция подключения по умолчанию NOCOUNT, что вызывало исключение ChangeConflictException для каждого обновления, сделанного с помощью Linq в Sql. Вы можете сослаться на мой пост здесь .
источник
Я исправил это, добавив
(UpdateCheck = UpdateCheck.Never)
ко всем[Column]
определениям.Однако это не похоже на подходящее решение. В моем случае это, похоже, связано с тем, что эта таблица связана с другой таблицей, из которой удаляется строка.
Это на Windows Phone 7.5.
источник
В моем случае ошибка возникла, когда два пользователя с разными контекстами данных LINQ-to-SQL обновили один и тот же объект одинаковым образом. Когда второй пользователь предпринял попытку обновления, его копия в контексте данных оказалась устаревшей, даже если она была прочитана после завершения первого обновления.
Я обнаружил объяснение и решение в этой статье Акшая Фадке: https://www.c-sharpcorner.com/article/overview-of-concurrency-in-linq-to-sql/
Вот код, который я в основном использовал:
Когда я посмотрел в окно вывода во время отладки, я увидел, что текущее значение соответствует значению базы данных. «Первоначальная ценность» всегда была виновата. Это было значение, прочитанное контекстом данных перед применением обновления.
Спасибо MarceloBarbosa за вдохновение.
источник
Я знаю, что на этот вопрос уже давно дан ответ, но здесь я провел последние несколько часов, биться головой о стену, и я просто хотел поделиться своим решением, которое, как оказалось, не связано ни с одним из пунктов в этой ветке:
Кеширование!
Часть select () моего объекта данных использовала кеширование. Когда дело дошло до обновления объекта, возникала ошибка «Строка не найдена или изменена».
В нескольких ответах упоминалось использование разных DataContext, и, оглядываясь назад, вероятно, это то, что происходило, но это не сразу заставило меня думать о кешировании, поэтому, надеюсь, это кому-то поможет!
источник
Недавно я столкнулся с этой ошибкой и обнаружил, что проблема не в моем контексте данных, а в том, что оператор обновления срабатывает внутри триггера после того, как в контексте вызывается фиксация. Триггер пытался обновить поле, не допускающее значения NULL, с помощью нулевого значения, и это вызывало ошибку контекста с сообщением, упомянутым выше.
Я добавляю этот ответ исключительно для того, чтобы помочь другим справиться с этой ошибкой и не нашел решения в ответах выше.
источник
Я также получил эту ошибку из-за использования двух разных контекстов. Я решил эту проблему, используя единый контекст данных.
источник
В моем случае проблема заключалась в настройках пользователя на уровне сервера. Следующий:
https://msdn.microsoft.com/en-us/library/ms190763.aspx
Я включил опцию NOCOUNT в надежде получить некоторые преимущества в производительности:
и это, оказывается, нарушает проверки Linq для затронутых строк (насколько я могу понять из источников .NET), что приводит к ChangeConflictException
Сброс параметров для исключения 512 бит устранил проблему.
источник
После использования ответа qub1n я обнаружил, что проблема для меня заключалась в том, что я случайно объявил столбец базы данных десятичным (18,0). Я назначал десятичное значение, но база данных меняла его, удаляя десятичную часть. Это привело к проблеме с изменением строки.
Просто добавьте это, если кто-то еще столкнется с аналогичной проблемой.
источник
просто используйте Linq2DB, намного лучше
источник