.NET 7/EF Core 7: у нас есть процесс, который отслеживает изменения в базе данных, и я не могу его контролировать. Это черный ящик.
Что я могу контролировать, так это методы сохранения этих изменений. В своей программе я хочу опустить записи, НЕ принадлежащие двум основным таблицам. Это хороший способ «очистить» эти записи с трекера? Или есть более приемлемый способ сделать это?
Наша база данных довольно мала: каждая таблица содержит <10 тыс. записей.
// first we only want to commit changes to Schedule and Vacation ONLY so get those entries which are not part of that set.
var unDbSets = context.ChangeTracker.Entries()
.Where(e => e.Entity is not Schedule && e.Entity is not Vacation)
.Where(p => p.State == EntityState.Added || p.State == EntityState.Deleted || p.State == EntityState.Modified)
.ToList();
foreach (var unDbSet in unDbSets)
{
if (unDbSet.State == EntityState.Added)
{
// entity was never in the DB so we just try detaching it. this way EF will stop tracking it and will not take any
// actions to serialize changes against DB.
// note: we had this originally to Unchanged but that throws an exception
unDbSet.State = EntityState.Detached;
}
else
{
// entity was in the DB so we just change the state to unchanged and it will not do anything with it and EF will leave
// it in its original state in the DB.
unDbSet.State = EntityState.Unchanged;
}
}
// finally save the tracker changes
context.SaveChanges();
В основном это предохранитель, чтобы, если они случайно будут добавлены в трекер, их просто удалили.
Я бы предпочел создать исключение. Вызывающая функция SaveChanges должна знать, что ее код неправильный или он пытался сделать что-то запрещенное. Если молча не сохранять данные, это может слишком долго оставаться незамеченным.
Опять же, в моей ситуации я не могу изменить восходящий поток. В идеальном мире да, это можно было бы исправить, но на данный момент это не вариант.
Хорошо, видимо, над этой частью больше никто не работает.
Речь идет о том, как настроить защиту с помощью DbContext, чтобы избежать неразрешенных изменений. Вариант: я использовал интерфейс маркера, чтобы отметить, какие объекты разрешено обновлять:
Т.е.
public interface IEditableEntity {}
Это можно привязать к любому базовому классу сущностей, возможно, вам придется централизовать свойства, такие как LastModifiedBy и LastModifiedDateTime и т. д., если вы включите их обработку в DbContext. Затем нужно разобраться с отклонением правок, вставок и т. д. Я обычно занимаюсь этим индивидуально, так как могу захотеть сообщить подробности о том, какие изменения отбрасываются.
var unAllowedUpdates = ChangeTracker.Entries().Any(x => x.State == EntityState.Modified
&& !typeof(IEditableEntity).IsAssignableFrom(x.GetType())));
В конечном итоге вы выполнили удаление этих элементов из системы отслеживания изменений, отсоединив добавления и установив измененные значения в неизмененные. Однако, если вы хотите полностью отменить эти изменения, вам также следует вызвать ChangeTracker.Clear()
после завершения SaveChanges()
, если после сохранения можно выполнить дополнительные запросы к экземпляру DbContext. Например, предположим, что у меня есть объект «Поездка», который имеет эти расписания, и по какой-либо причине поездка может быть обновлена, и я не хочу, чтобы она сохранялась, но я хочу сохранить дополнения и обновления в расписаниях. При сохранении данных я могу установить для Trip значение Unchanged, чтобы эти изменения не записывались, но если код снова загрузит поездку из DbContext, он все равно получит мою измененную (но неизмененную) сущность Trip в кеше отслеживания. чем извлечение реального состояния данных. Если вы намерены отменить изменения, но по-прежнему готовы видеть возможные изменения после сохранения (которые на самом деле не сохранились), то вы не хотите очищать трекер изменений, но если вы хотите, чтобы отброшенные изменения отражались в любых дальнейших вызовах из этот экземпляр DbContext, то вам следует очистить трекер изменений после сохранения, если изменения были отменены/игнорированы.
Ааааааааа, это был своего рода дополнительный вопрос, но я не хотел засорять пост. Так что да, фактически после того, как произойдет SaveChanges, пользователь все равно сможет внести дополнительные изменения, а затем снова сохранить те же записи. Хорошо, позвольте мне протестировать это и вернуться через день или два.
Работает как задумано. Спасибо.
«Это хороший способ «очистить» эти записи?» Вы вообще не указываете, почему вы хотите это сделать, поэтому мы не можем предложить вам лучшие методы.