System.Data.Linq.ChangeConflictException: строка не найдена или изменена
Я пытаюсь удалить выбранную строку gridview с помощью LINQ (No
LinqDataSource).
Когда выбор изменен, привязка привязки к объекту изменяется
также. Я могу добавить новую запись в базу данных, но когда я добавил
код на кнопку удаления внутри updatePanel, я получил исключение:
try
{
var query = from i in db.QuestionModules
where i.QuestionModuleID == QuestionModuleID
select i;
QuestionModule o = query.First();
db.QuestionModules.DeleteOnSubmit(o);
db.SubmitChanges();
}
Это исключение, которое я получаю:
System.Data.Linq.ChangeConflictException: Row not found or changed. at
System.Data.Linq.ChangeProcessor.SubmitChanges(ConflictMode
failureMode) at
System.Data.Linq.DataContext.SubmitChanges(ConflictMode failureMode)
at System.Data.Linq.DataContext.SubmitChanges()
У меня была эта проблема около недели, и независимо от того, что я делаю, это
все еще там, и запись не удаляется.
Любые идеи о том, что делать?
Ответы
Ответ 1
ОК - похоже, что (по крайней мере, в моем случае) ответ заключался в том, чтобы установить для всех свойств первичного ключа UpdateCheck значение Never в DBML файле. Это немедленно устранило проблему "Строка не найдена или не изменена".
Учитывая слухи о том, что Microsoft является мотылькой Linq-To-Sql в пользу Entity Framework, задается вопросом, будут ли исправлены эти типы ошибок?
Ответ 2
Вы получаете эту ошибку вполне возможно, потому что одно из ваших полей имеет что-то другое в конструкторе Linq To SQL и в фактической базе данных.
В моем случае это было потому, что одно из полей было нулевым в базе данных и не было нулевым в дизайнере, что сделало его нулевым в дизайнере, а также решило проблему немедленно.
Ответ 3
У меня такая же проблема, и я встретил этот блог, в котором в основном говорится, что у Linq-To-Sql есть проблема в он оптимистичен concurrency где:
- Используются поля высокой точности datetime. Решение заключается в том, чтобы установить UpdateCheck никогда не для этого столбца в файле DBML
- Столбцы GridView, которые настроены на невидимость, получают доступ к свойству объекта данных (эта вторая причина не имеет смысла, но, похоже, все это ярость в этом блоге).
Я еще не пробовал эти решения, но вернусь сюда, когда найду.
Ответ 4
Проблема также может заключаться в том, что определение таблицы DBML не соответствует статусу определения базы данных. Я просто удалил модель DBML и снова вставил ее из базы данных, и она сработала.
Надеюсь, это поможет кому-то.
Ответ 5
Я обошел эту проблему, убедившись, что я обновил свой объект непосредственно перед его обновлением. Я делаю это с помощью опции KeepChanges.
db.Refresh(System.Data.Linq.RefreshMode.KeepChanges, employee);
Ответ 6
Казалось, что я тоже работаю над своей ситуацией. Я создавал в памяти, никогда ранее не представленную строку, которая имела несколько внешних ключей для строк в других таблицах. Возможно, InsertOnSubmit работал, но последующий DeleteOnSubmit давал мне эту строку, которая не обнаружила ошибку. Я не заполнял каждое поле в строке, которую я отправил, поэтому я не знаю, имело ли это какое-либо отношение к ней, но отмечая все столбцы основного нестандартного ключевого столбца, удалило сообщение об ошибке.
Еще одна мысль: я считаю, что маркировка политики UpdateCheck в столбце как "Никогда" означает, что она не используется в качестве основы для оптимистической проверки соответствия. Это означало бы, что два пользователя могут писать по данной строке с разными данными в любом таком столбце, и конфликты не будут обнаружены... что означает, что последний пользователь должен отправить строку, чтобы перезаписать значения предыдущей заявки пользователя. Из различных онлайн-показаний я понял, что одним из частичных решений является использование метода Refresh непосредственно перед отправкой для синхронизации любых изменений. Конечно, без пезимистической блокировки в строке нет гарантии, что строка не будет изменяться между Refresh и Submit, но в большинстве сценариев, связанных с большими базами данных, это было бы редко.
Обновление: при дальнейших проверках я думаю, что я обнаружил сценарий, который может повлиять на других, поэтому я решил поделиться им на всякий случай. Оказывается, что по крайней мере часть проблемы, с которой я столкнулась с SQL LINQ, связана с триггерами. Похоже, что если вы отправляете строку с использованием SQL LINQ, и у вашего администратора базы данных есть триггеры, предназначенные для записи информации в некоторые столбцы в этой строке, тогда модель SQL LINQ по умолчанию "Всегда" определяет, что строка была изменена с момента последней записи ее, Я отправлял частично заполненные строки, и наши триггеры DBA заполняют некоторые столбцы, поэтому, когда я пытался изменить строку в нашем коде, он обнаружил конфликт изменений на основе столбцов, заполненных триггером. Сейчас я изучаю лучший способ справиться с этим, но изменение этих триггерных полей для использования политики UpdateCheck для "When Changed" или "Never" работает для меня. Надеюсь, что это поможет.
Ответ 7
Это просто случай несогласованных определений столбцов. Просто удалите таблицу из .dbml
и снова добавьте. Не забудьте изменить auto generate value property = true
для столбцов с автоматическими сгенерированными данными, такими как первичные ключи или столбцы datetime.
Ответ 8
У меня было аналогичное changeconflictexception/ "Строка не найдена или изменена" при обновлении строки.
Решила его, добавив табуляции в dbml.
Ответ 9
Проблема была в том, что у меня был тип DateTime в .net framework, но в нашем поле базы данных был тип DateTime2, который является более высокоточным типом данных. Поэтому, когда мы будем отправлять изменения, поля даты объекта и БД находились всего в несколько наносекунд, что вызвало бы ошибку concurrency. Это произошло, когда мы перешли на новую версию MSSQL и преобразуем наши поля DateTime в DateTime2.
Итак, в нашем коде, где у нас было:
Obj.DateUpdated = DateTime.Now()
Мы изменили его на:
Obj.DateUpdated = DateTime.Parse(DateTime.Now.ToString())
Поэтому проверьте свои типы данных, особенно ваши поля даты, если вы получите эту ошибку после обновления и/или миграции.
Ответ 10
Убедитесь, что ни один столбец не содержит значений null
в связанной таблице (т.е. обновляемая таблица).
Ответ 11
Под:
QuestionModule o = query.First();
Вам нужно добавить следующую команду:
db.QuestionModule.Attach(o);
Ответ 12
Мне удалось решить эту проблему, выполнив databind() в gridview и datasource во время обратной передачи backpanel.
protected void UpdatePanel1_Load(object sender, EventArgs e)
{
GridView1.DataBind();
LinqDataSource1.DataBind();
}
Я обновляю updatepanel каждый раз, когда меняет индекс выбора, и он смог разрешить конфликты.
Надеюсь, что это поможет.
Ответ 13
Кроме того - если вы вызываете метод выбора для linqdatasource и вручную устанавливаете e.result, убедитесь, что вы также включаете значения других ключей.
Ничто другое не работало для меня, но это.
Ответ 14
Как я исправил это: сначала я обновляю базу данных, а затем устанавливаю новые значения для сетки как
e.Keys["ColumnOne"] ="new value"
e.Keys["ColumnTwo"] ="new value"
Все это было сделано при событии GridView_RowUpdating
.
Ответ 15
Я просто хотел добавить свой сценарий для тех, у кого может быть эта проблема.
Мы используем пользовательский T4 для нашего Linq to SQL dbml. Мы в основном просто модифицировали исходный get/set строковых свойств, чтобы автоматически обрезать и установить нуль.
get { return _OfficiantNameMiddle.GetValueOrNull(); }
set
{
value = value.GetValueOrNull();
if (_OfficiantNameMiddle != value)
{
_IsDirty = true;
OnOfficiantNameMiddleChanging(value);
SendPropertyChanging("OfficiantNameMiddle");
_OfficiantNameMiddle = value;
SendPropertyChanged("OfficiantNameMiddle");
OnOfficiantNameMiddleChanged();
}
}
У устаревших данных в нашей базе данных были некоторые ведущие/конечные пробелы, поэтому любая проверка concurrency этих столбцов не привела к совпадению (это сравнение обрезанного значения по отношению к значению базы данных без обрезки). Было очень легко профилировать SQL, захватить SQL и начать комментирование элементов в предложении WHERE до тех пор, пока он не начнет возвращать строку во время проверки concurrency.
К счастью, у нас есть поле LastUpdatedOn в наших таблицах, которое автоматически устанавливается через OnValidate (System.Data.Linq.ChangeAction).
partial void OnValidate(System.Data.Linq.ChangeAction action)
{
if (action == System.Data.Linq.ChangeAction.Insert)
{
CreatedBy = CurrentUserID;
CreatedOn = DateTime.Now;
LastUpdatedBy = CreatedBy;
LastUpdatedOn = CreatedOn;
}
else if (action == System.Data.Linq.ChangeAction.Update)
{
LastUpdatedBy = CurrentUserID;
LastUpdatedOn = DateTime.Now;
}
}
Чтобы обойти проблему, мы просто устанавливаем для параметра concurrency значение "Никогда" для всех столбцов, кроме столбцов первичного ключа и столбца LastUpdatedOn. Это сработало для нас.
Ответ 16
У меня была аналогичная проблема, и хотя удаление и повторное добавление таблицы/класса DBML помогло некоторым пользователям, для меня это было немного иначе, поскольку я использую WCF с отдельным элементом и ListView на клиенте.
Если я использовал .Attach(сущность), он потерпел неудачу - "Строка не найдена или не изменена"
Но при использовании .Attach(entity, original) он работает каждый раз
public void DeleteTask(Task task)
{
TwoDooDataContext db = new TwoDooDataContext();
db.Tasks.Attach(task,GetTaskByID(task.ID));
db.Tasks.DeleteOnSubmit(task);
db.SubmitChanges();
}
Ответ 17
Для меня это был столбец перечисления (сопоставленный с varchar), который вызвал проблему, поэтому мне пришлось пройти проверку обновлений, чтобы никогда.
Ответ 18
Как указано в @dherrin79, это может быть вызвано из-за точности дисперсии между базой данных и кодом. Для меня проблема заключалась в том, что столбец базы данных должен был быть десятичным (10,2), но он был создан как десятичный (18,0). Это было для денежного поля, поэтому, возможно, я должен был использовать тип столбца денег.
Итак, я сохранил сумму в долларах, например, $3.14, но десятичный разделился. Это привело к изменению значения базы данных и не соответствует значению в С#.
Надеюсь, что это поможет.