Как очистить отслеживаемые объекты в инфраструктуре сущности
Я запускаю некоторый код исправления, который выполняется над большой кучей сущностей, поскольку он ускоряет его скорость, то есть потому, что количество отслеживаемых объектов в контексте увеличивается с каждой итерацией. Это может занять много времени, поэтому я сохраняю изменения в конце каждой итерации. Каждая итерация независима и не изменяет ранее загруженные объекты.
Я знаю, что могу отключить отслеживание изменений, но я этого не хочу, потому что это не полный код вставки, а загрузка объектов и вычисление нескольких вещей, и если числа неверны, установите новые номера и обновите/удалить/создать несколько дополнительных объектов. Я знаю, что я могу создать новый DbContext для каждой итерации, и, вероятно, это будет работать быстрее, чем все в одном экземпляре, но я думаю, что может быть лучший способ.
Итак, вопрос: Есть ли способ очистить объекты, ранее загруженные в контексте db?
Ответы
Ответ 1
Вы можете добавить метод к вашему DbContext
или метод расширения, который использует ChangeTracker, чтобы отсоединить все добавленные, измененные и удаленные объекты:
public void DetachAllEntities()
{
var changedEntriesCopy = this.ChangeTracker.Entries()
.Where(e => e.State == EntityState.Added ||
e.State == EntityState.Modified ||
e.State == EntityState.Deleted)
.ToList();
foreach (var entry in changedEntriesCopy)
entry.State = EntityState.Detached;
}
Ответ 2
1. Возможность: отсоединить запись
dbContext.Entry(entity).State = EntityState.Detached;
Когда вы отсоединяете запись, трекер изменений перестает ее отслеживать (что должно привести к повышению производительности).
Смотрите: http://msdn.microsoft.com/de-de/library/system.data.entitystate(v=vs.110).aspx
2. Возможность: работать со своим собственным полем Status
+ отключенные контексты
Может быть, вы хотите контролировать статус вашей сущности независимо, чтобы вы могли использовать отключенные графики. Добавьте свойство для статуса объекта и преобразуйте его в dbContext.Entry(entity).State
при выполнении операций (используйте для этого репозиторий)
public class Foo
{
public EntityStatus EntityStatus { get; set; }
}
public enum EntityStatus
{
Unmodified,
Modified,
Added
}
См. Следующую ссылку для примера: https://www.safaribooksonline.com/library/view/programming-entity-framework/9781449331825/ch04s06.html
Ответ 3
Я запускаю службу Windows, которая обновляет значения каждую минуту, и у меня была та же проблема. Я попытался запустить решение @DavidSherrets, но через несколько часов это тоже стало медленным. Моим решением было просто создать новый контекст, подобный этому, для каждого нового запуска. Просто, но это работает.
_dbContext = new DbContext();
Ответ 4
Я только столкнулся с этой проблемой и в конце концов наткнулся на лучшее решение для тех, кто использует типичное внедрение зависимостей .NET Core. Вы можете использовать ограниченный DbContext для каждой операции. Это сбросит DbContext.ChangeTracker
так что SaveChangesAsync()
не будет DbContext.ChangeTracker
проверке сущностей из прошлых итераций. Вот пример метода ASP.NET Core Controller:
/// <summary>
/// An endpoint that processes a batch of records.
/// </summary>
/// <param name="provider">The service provider to create scoped DbContexts.
/// This is injected by DI per the FromServices attribute.</param>
/// <param name="records">The batch of records.</param>
public async Task<IActionResult> PostRecords(
[FromServices] IServiceProvider provider,
Record[] records)
{
// The service scope factory is used to create a scope per iteration
var serviceScopeFactory =
provider.GetRequiredService<IServiceScopeFactory>();
foreach (var record in records)
{
// At the end of the using block, scope.Dispose() will be called,
// release the DbContext so it can be disposed/reset
using (var scope = serviceScopeFactory.CreateScope())
{
var context = scope.ServiceProvider.GetService<MainDbContext>();
// Query and modify database records as needed
await context.SaveChangesAsync();
}
}
return Ok();
}
Учитывая, что проекты ASP.NET Core обычно используют DbContextPool, это даже не создает/уничтожает объекты DbContext. (Если вам интересно, DbContextPool на самом деле вызывает DbContext.ResetState()
и DbContext.Resurrect()
, но я бы не рекомендовал вызывать их напрямую из вашего кода, так как они, вероятно, изменятся в будущих выпусках.) Https://github.com/САШ /EntityFrameworkCore/BLOB/v2.2.1/SRC/EFCore/Внутренний /DbContextPool.cs # L157