haz*_*nli 52 c# entity-framework
我正在运行一些运行在一大堆实体上的校正码,因为它的速度会降低,这是因为上下文中跟踪实体的数量会随着每次迭代而增加,这可能需要很长时间,所以我最后会保存更改每次迭代.每次迭代都是独立的,不会改变先前加载的实体.
我知道我可以关闭更改跟踪,但我不想,因为它不是批量插入代码,而是加载实体并计算一些东西,如果数字不正确,请设置新数字并更新/删除/创建一些额外的实体.我知道我可以为每次迭代创建一个新的DbContext,并且可能比在同一个实例中执行所有操作更快,但我认为可能有更好的方法.
所以问题是; 有没有办法清除先前在db上下文中加载的实体?
Dav*_*ret 84
您可以向您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;
}
Run Code Online (Sandbox Code Playgroud)
j-p*_*tty 33
EntityFramework Core 5.0 引入了一种新方法来清除任何跟踪的更改。
_context.ChangeTracker.Clear();
Run Code Online (Sandbox Code Playgroud)
roa*_*242 17
1.可能性:分离条目
dbContext.Entry(entity).State = EntityState.Detached;
Run Code Online (Sandbox Code Playgroud)
当您分离条目时,更改跟踪器将停止跟踪它(并且应该导致更好的性能)
请参阅: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
}
Run Code Online (Sandbox Code Playgroud)
请参阅以下链接以获取示例:https://www.safaribooksonline.com/library/view/programming-entity-framework/9781449331825/ch04s06.html
Ogg*_*las 12
我正在运行一个每分钟更新值的Windows服务,我遇到了同样的问题.我试过运行@DavidSherrets解决方案,但几个小时后这也变慢了.我的解决方案是为每次新的运行创建一个像这样的新上下文.简单但它的工作原理.
_dbContext = new DbContext();
我刚刚遇到了这个问题,最终偶然发现了一个更好的解决方案,适用于那些使用典型的 .NET Core 依赖注入的人。您可以为每个操作使用一个作用域 DbContext。这将重置,DbContext.ChangeTracker以便SaveChangesAsync()不会因为过去的迭代检查实体而陷入困境。这是一个示例 ASP.NET Core 控制器方法:
/// <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();
}
Run Code Online (Sandbox Code Playgroud)
鉴于 ASP.NET Core 项目通常使用 DbContextPool,这甚至不会创建/销毁 DbContext 对象。(如果您有兴趣,DbContextPool 实际上会调用DbContext.ResetState()和DbContext.Resurrect(),但我不建议直接从您的代码中调用它们,因为它们可能会在未来版本中发生变化。)
https://github.com/aspnet/EntityFrameworkCore/blob/v2 .2.1/src/EFCore/Internal/DbContextPool.cs#L157