2009-04-30 4 views
51

Я пытаюсь удалить выбранную строку сетки с помощью LINQ (No LINQDataSource).System.Data.Linq.ChangeConflictException: строка не найдена или не изменена

При изменении выбора связывание с подробным представлением изменяется и на . Я могу добавить новую запись в базу данных, но когда я добавил этот код для удаления кнопки внутри 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() 

У меня была эта проблема около недели, и независимо от того, что я делаю, это еще , и запись не удаляется.

Любые идеи о том, что делать?

ответ

15

У меня та же проблема, и наткнулся на this blog, который в основном говорится, что Linq-To-Sql получил проблему в это оптимистичный параллелизм где используются

  1. Высокоточные поля DateTime. Решение состоит в том, чтобы установить UpdateCheck никогда не для этого столбца, ваш DBML-файл
  2. Столбцы GridView, которые установлены в невидимые, получают доступ к свойству объекта данных (эта вторая причина не имеет смысла, но, похоже, блог).

Я еще не пробовал эти решения, но после этого отправлю его обратно.

+0

OK - Я только что попробовал установить Update Update для Yes, чтобы никогда ... нет радости, я все равно получаю тот же результат. – Mark

+0

У меня была такая же проблема с некоторым обновлением поля даты и времени: изменение значения UpdateCheck решило проблему. –

+2

+1 У меня была эта проблема с полем «float» в SQL DB, которое я сопоставил с типом «float» (single) на C#. Когда я изменил тип на «double», проблема исчезла. Но именно этот ответ меня опрокинул - так СПАСИБО! –

66

OK - это выглядит, как если бы (в моем случае, по крайней мере) ответ был установить свойства UpdateCheck всего не первичный ключ столбца в Никогда в файле DBML. Это немедленно устранило проблему «Строка не найдена или не изменена».

Учитывая слухи о том, что Microsoft является мотылькой Linq-To-Sql в пользу Entity Framework, задается вопросом, будут ли исправлены эти виды ошибок?

+1

Это может сработать, но черт возьми, желательно? Не для меня! –

+0

+1 как он работал. может ли кто-нибудь пролить. некоторый свет на последствиях этого. Сообщение в блоге или иначе было бы здорово. Благодарю. – Kieran

+1

И если у меня есть gazillion колонки ... – keni

0

Under:

QuestionModule o = query.First(); 

Вы должны добавить следующую команду:

db.QuestionModule.Attach(o); 
1

Убедитесь, что столбцы не содержат null значения в соответствующей таблице (то есть таблицы для обновления).

+0

Как в мире кто-нибудь будет использовать L2S без какой-либо ошибки в любом поле БД? –

+0

Это решение сработало для меня. Просто изменили все значения NULL на то, что должно быть по умолчанию, хотя db должен поддерживать NULL в этом столбце. –

0

Я смог решить эту проблему, выполнив databind() на gridview и datasource во время обратной передачи backpanel.

protected void UpdatePanel1_Load(object sender, EventArgs e) 
    { 
     GridView1.DataBind(); 
     LinqDataSource1.DataBind(); 
    } 

Я обновляю updatepanel каждый раз, когда меняет индекс выбора, и он смог разрешить конфликты.

Надеюсь, что это поможет.

6

Казалось, что для моей ситуации тоже. Я создавал в памяти, никогда ранее не представленную строку, которая имела несколько внешних ключей для строк в других таблицах.Возможно, InsertOnSubmit работал, но последующий DeleteOnSubmit давал мне эту строку, которая не обнаружила ошибку. Я не заполнял каждое поле в строке, которую я отправил, поэтому я не знаю, имело ли это какое-либо отношение к ней, но отмечая все столбцы непервичного ключа основной таблицы, устранило сообщение об ошибке.

Еще одна мысль: я считаю, что маркировка политики UpdateCheck в столбце «Никогда» означает, что она не используется в качестве основы для оптимистической проверки соответствия. Это означало бы, что два пользователя могут писать по данной строке с разными данными в любом таком столбце, и конфликты не будут обнаружены ... что означает, что последний пользователь должен отправить строку, чтобы перезаписать значения предыдущей заявки пользователя. Из различных онлайн-показаний я понял, что одним из частичных решений является использование метода Refresh непосредственно перед отправкой для синхронизации любых изменений. Конечно, без пезимистической блокировки в строке нет гарантии, что строка не будет изменяться между Refresh и Submit, но в большинстве сценариев, связанных с большими базами данных, это было бы редко.

Обновление: при дальнейшем рассмотрении, я думаю, что я обнаружил сценарий, который может повлиять на других, поэтому я решил поделиться им на всякий случай. Оказывается, что по крайней мере часть проблемы, с которой я столкнулась с SQL LINQ, связана с триггерами. Похоже, что если вы отправляете строку с использованием SQL LINQ, и у вашего администратора базы данных есть триггеры, предназначенные для записи информации в некоторые столбцы в этой строке, тогда модель SQL LINQ по умолчанию «Всегда» определяет, что строка была изменена с момента последней записи ее , Я отправлял частично заполненные строки, и триггеры нашего DBA заполняют некоторые столбцы, поэтому, когда я попытался изменить строку в нашем коде, он обнаружил конфликт изменений, основанный на столбцах, заполненных триггером. Сейчас я изучаю лучший способ справиться с этим, но изменение этих триггерных полей для использования политики UpdateCheck для «When Changed» или «Never» работает для меня. Надеюсь, поможет.

+0

Спасибо, что указали мне в направлении 'UpdateCheck' ... – ctrlShiftBryan

2

У меня было подобное changeconflictexception/«Ряд не найден или изменен» при обновлении строки. Решил его, повторно добавив табуляции в dbml.

12

Проблема может заключаться также в том, что определение таблицы DBML не соответствует статусу определения базы данных. Я просто удалил модель DBML и снова вставил ее из базы данных, и она сработала.

Надеюсь, это поможет кому-то.

+0

это лучший ответ –

46

Вы получаете эту ошибку, возможно, потому, что одно из ваших полей имеет что-то другое в конструкторе Linq To SQL и в реальной базе данных.

В моем случае это было потому, что одно из полей было нулевым в базе данных и не было равно NULL в дизайнере, что сделало его нулевым в дизайнере, а также решило проблему немедленно.

+3

Missmatch в DBML и базе данных была моей проблемой. – Andreas

+0

Правильно, я так и думал. Представьте, что рекомендация установить «все» столбцы на какое-то значение имеет больше голосов :( – keni

0

Кроме того - если вы вызываете метод выбора для linqdatasource и устанавливаете e.result вручную, убедитесь, что вы также включаете в себя значения посторонних ключей.

Ничто другое не работало для меня, кроме этого.

0

Путь я установил это было: Сначала я обновить базу данных, то я установить новые значения сетки в качестве

e.Keys["ColumnOne"] ="new value" 
e.Keys["ColumnTwo"] ="new value" 

Все это было сделано в рамках GridView_RowUpdating мероприятия.

0

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

Мы используем пользовательский 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(); 
      } 
     } 

Устаревшие данные в нашей базе были некоторые ведущие/ведомые пробелы так что любая проверка параллельности на этих колонках не удалось привести в матче (он сравнивал обрезанного значение по отношению к значению, не урезанный базы данных). Было очень легко профилировать SQL, захватить SQL и начать комментирование элементов в предложении WHERE до тех пор, пока он не начнет возвращать строку во время проверки параллелизма.

К счастью, у нас есть поле 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; 
     } 
    } 

Чтобы обойти эту проблему, мы просто установить проверку параллельности в коем случае не на всех столбцов, кроме столбцов первичного ключа и колонки LastUpdatedOn. Это сработало для нас.

0

У меня была аналогичная проблема. Хотя удаление и повторное добавление таблицы/класса DBML помогло некоторым пользователям, для меня это было немного иначе, так как я использую WCF с отдельным объектом и ListView на клиенте.

Если я использовал .Attach (юридическое лицо), он не смог - «Строка не найдена или изменена» Но при использовании .Attach (юридического лица, оригинальный) он работает каждый раз

public void DeleteTask(Task task) 
    { 
     TwoDooDataContext db = new TwoDooDataContext(); 
     db.Tasks.Attach(task,GetTaskByID(task.ID)); 
     db.Tasks.DeleteOnSubmit(task); 
     db.SubmitChanges(); 
    } 
0

Для меня это было перечислимый столбец (сопоставленный с varchar), который вызвал проблему, поэтому мне пришлось пройти проверку обновлений до конца.

8

Я обошел эту проблему, убедившись, что обновил свой объект непосредственно перед его обновлением. Я делаю это с помощью опции KeepChanges.

db.Refresh(System.Data.Linq.RefreshMode.KeepChanges, employee); 
+0

Это, похоже, решило мои проблемы. Еще одна услуга может одновременно обновлять эту запись, и мне нужно было обновить ее перед отправкой. – Smeiff

+0

Это работало как шарм для я ... после нескольких часов борьбы! – jharr100

2

Проблема у меня было то, что я имел тип DateTime в рамках .net, но наше поле базы данных было типа Datetime2, что более высокая точность тип данных. Поэтому, когда мы будем вводить изменения, поля даты объекта и БД находились всего в нескольких наносекундах, что могло бы вызвать ошибку параллелизма. Это произошло, когда мы перешли на новую версию MSSQL и конвертировали наши поля DateTime в DateTime2.

Таким образом, в нашем коде, где мы были:

Obj.DateUpdated = DateTime.Now() 

Мы изменили его:

Obj.DateUpdated = DateTime.Parse(DateTime.Now.ToString()) 

Так проверить типы данных, особенно ваши поля даты, если вы получите эту ошибку после того, как сделать обновление и/или миграции.

3

Это всего лишь случай несоответствующих определений столбцов. Просто удалите таблицу с .dbml и снова добавьте. Обязательно измените значение auto generate value property = true для столбцов с автоматическими генерируемыми данными, такими как первичные ключи или столбцы datetime.

0

Как указано в @ dherrin79, это может быть вызвано из-за точной дисперсии между базой данных и кодом. Для меня проблема заключалась в том, что столбец базы данных должен был быть десятичным (10,2), но он был создан как десятичный (18,0). Это было для денежного поля, поэтому, возможно, я должен был использовать тип столбца денег.

Итак, я сохранил сумму в долларах, например 3,14 доллара, но десятичную сумму разделили. Это привело к изменению значения базы данных и не соответствует значению в C#.

Надеюсь, что это поможет.

Смежные вопросы