Подтвердить что ты не робот

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() 

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

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

4b9b3361

Ответ 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, но десятичный разделился. Это привело к изменению значения базы данных и не соответствует значению в С#.

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