это может быть тривиальный вопрос, но: Поскольку структура сущностей ADO.NET автоматически отслеживает изменения (в сгенерированных сущностях) и, следовательно, сохраняет исходные значения, как я могу отменить изменения, внесенные в объекты сущностей?
У меня есть форма, которая позволяет пользователю редактировать набор сущностей «Клиент» в виде сетки.
Теперь у меня есть две кнопки «Принять» и «Вернуть»: если щелкнуть «Принять», я вызываю, Context.SaveChanges()
и измененные объекты записываются обратно в базу данных. Если щелкнуть «Вернуть», я хотел бы, чтобы все объекты получили свои исходные значения свойств. Какой для этого будет код?
Спасибо
источник
Context.Refresh()
, это контрпример к вашему утверждению об отсутствии операции возврата? ИспользованиеRefresh()
кажется лучшим подходом (т.е. более легко нацеленным на определенные объекты), чем удаление контекста и потеря всех отслеживаемых изменений.Запросить ChangeTracker из DbContext на предмет «грязных» элементов. Установите состояние удаленных элементов как неизменное, а добавленные элементы - как отключенные. Для измененных элементов используйте исходные значения и установите текущие значения записи. Наконец, установите состояние измененной записи без изменений:
источник
State
для EntityState.Unchanged перекроет все значения сOriginal Values
, а поэтому нет необходимости вызоваSetValues
метода.Согласно MSDN :
Обратите внимание, что возврат через запрос к базе данных имеет некоторые недостатки:
источник
Это сработало для меня:
Где
item
должна быть восстановлена организация-покупатель.источник
Простой способ без отслеживания изменений. Это должно быть быстрее, чем смотреть на каждую сущность.
источник
Rollback
описанная выше процедура, что делает его гораздо лучшим выбором, если кто-то хочет полностью восстановить состояние базы данных. Откат может быть лучше.50ms+0*n= 50ms
. O (n) означает, что на производительность влияет количество объектов ... производительность может быть2ms+0.5ms*n
... так что ниже 96 объектов это будет быстрее, но время будет линейно увеличиваться с объемом данных.У меня это сработало. Однако вы должны перезагрузить данные из контекста, чтобы восстановить старые данные. Источник здесь
источник
"У меня сработало:
Где
item
должна быть восстановлена организация-покупатель ".Я провел тесты с ObjectContext.Refresh в SQL Azure, и RefreshMode.StoreWins запускает запрос к базе данных для каждого объекта и вызывает утечку производительности. На основе документации Microsoft ():
ClientWins: изменения свойств, внесенные в объекты в контексте объекта, не заменяются значениями из источника данных. При следующем вызове SaveChanges эти изменения отправляются в источник данных.
StoreWins: изменения свойств, внесенные в объекты в контексте объекта, заменяются значениями из источника данных.
ClientWins тоже не является хорошей идеей, потому что запуск .SaveChanges зафиксирует "отклоненные" изменения в источнике данных.
Я еще не знаю, как лучше всего, потому что удаление контекста и создание нового вызывает исключение с сообщением: «Базовый провайдер не удалось открыть», когда я пытаюсь выполнить любой запрос в новом созданном контексте.
С уважением,
Энрике Клаузинг
источник
На мой взгляд, лучший способ сделать это - установить
EntityState.Unchanged
для каждого объекта, для которого вы хотите отменить изменения. Это гарантирует возврат изменений в FK и имеет немного более понятный синтаксис.источник
Я обнаружил, что это нормально работает в моем контексте:
Context.ObjectStateManager.ChangeObjectState(customer, EntityState.Unchanged);
источник
DbContext.SaveChanges()
, но не вернет значения объекта к исходным значениям. И если состояние объекта будет изменено в результате более позднего изменения, возможно, все предыдущие изменения сохранятся при сохранении?Это пример того, о чем говорит Мрнка. Следующий метод перезаписывает текущие значения объекта исходными значениями и не вызывает базу данных. Мы делаем это, используя свойство OriginalValues объекта DbEntityEntry, и используем отражение для установки значений обычным способом. (Это работает с EntityFramework 5.0)
источник
Мы используем EF 4 с контекстом устаревшего объекта. Ни одно из вышеперечисленных решений не дало мне прямого ответа на этот вопрос, хотя в конечном итоге оно ДЕЙСТВИТЕЛЬНО ответило на него, подтолкнув меня в правильном направлении.
Мы не можем просто удалить и перестроить контекст, потому что некоторые объекты, которые мы храним в памяти (черт возьми, эта ленивая загрузка !!), все еще прикреплены к контексту, но имеют дочерние элементы, которые еще не загружены. В этих случаях нам нужно вернуть все к исходным значениям, не забивая базу данных и не разрывая существующее соединение.
Ниже представлено наше решение этой же проблемы:
Надеюсь, это поможет другим.
источник
Некоторые хорошие идеи выше, я решил реализовать ICloneable, а затем простой метод расширения.
Найдено здесь: Как клонировать общий список в C #?
Используется как:
Таким образом, я смог клонировать свой список сущностей продукта, применить скидку к каждому элементу и не беспокоиться об отмене каких-либо изменений в исходной сущности. Нет необходимости разговаривать с DBContext и просить обновления или работать с ChangeTracker. Вы можете сказать, что я не использую EF6 в полной мере, но это очень хорошая и простая реализация, позволяющая избежать попадания в базу данных. Я не могу сказать, влияет ли это на производительность.
источник