简体   繁体   English

如何清除实体框架中的跟踪实体

[英]How do I clear tracked entities in entity framework

I am running some correction code that runs over a big pile of entities, as it progress its speed decreases, that is because the number of tracked entities in the context increase with each iteration, It can take long so I am saving changes at the end of each iteration.我正在运行一些在一大堆实体上运行的更正代码,随着它的进展速度降低,这是因为上下文中跟踪的实体数量随着每次迭代而增加,这可能需要很长时间,所以我在最后保存更改每次迭代。 Each iteration is independent and does not change the previosuly loaded entities.每次迭代都是独立的,不会改变先前加载的实体。

I know I can turn off change tracking but I do not want to, because it is not a bulk insert code, but loading the entities and calculating a few things and if the numbers are not correct set the new numbers and update/delete/create some additional entities.我知道我可以关闭更改跟踪,但我不想,因为它不是批量插入代码,而是加载实体并计算一些事情,如果数字不正确,请设置新数字并更新/删除/创建一些额外的实体。 I know I can create a new DbContext for each iteration and probably that would run faster than doing all in the same instance, but I am thinking that there might be a better way.我知道我可以为每次迭代创建一个新的 DbContext 并且可能比在同一实例中执行所有操作运行得更快,但我认为可能有更好的方法。

So the question is;所以问题是; Is there a way of clearing the entities previously loaded in the db context?有没有办法清除先前加载在 db 上下文中的实体?

You can add a method to your DbContext or an extension method that uses the ChangeTracker to detach all the Added, Modified, and Deleted entities:您可以向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;
}

1. Possibility: detach the entry 1. 可能性:分离入口

dbContext.Entry(entity).State = EntityState.Detached;

When you detach the entry the change tracker will stop tracking it (and should result in better performance)当您分离条目时,更改跟踪器将停止跟踪它(并且应该会产生更好的性能)

See: http://msdn.microsoft.com/de-de/library/system.data.entitystate(v=vs.110).aspx请参阅: http : //msdn.microsoft.com/de-de/library/system.data.entitystate(v=vs.110).aspx

2. Possibility: work with your own Status field + disconnected contexts 2. 可能性:使用您自己的Status字段 + 断开连接的上下文

Maybe you want to control the status of your entity independently so you can use disconnected graphs.也许您想独立控制实体的状态,以便您可以使用断开连接的图形。 Add a property for the entity status and transform this status into the dbContext.Entry(entity).State when performing operations (use a repository to do this)为实体状态添加一个属性,并在执行操作时将此状态转换为dbContext.Entry(entity).State (使用存储库来执行此操作)

public class Foo
{
    public EntityStatus EntityStatus { get; set; }
}

public enum EntityStatus
{
    Unmodified,
    Modified,
    Added
}

See following link for an example: https://www.safaribooksonline.com/library/view/programming-entity-framework/9781449331825/ch04s06.html请参阅以下链接以获取示例: https : //www.safaribooksonline.com/library/view/programming-entity-framework/9781449331825/ch04s06.html

EntityFramework Core 5.0 introduced a new method to clear any tracked changes. EntityFramework Core 5.0 引入了一种新方法来清除任何跟踪的更改。

_context.ChangeTracker.Clear();

https://docs.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.changetracking.changetracker.clear?view=efcore-5.0 https://docs.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.changetracking.changetracker.clear?view=efcore-5.0

I'm running a windows service that updates values every minute and I have had the same problem.我正在运行一个每分钟更新一次值的 Windows 服务,我遇到了同样的问题。 I tried running @DavidSherrets solution but after a few hours this got slow as well.我尝试运行@DavidSherrets 解决方案,但几个小时后这也变慢了。 My solution was to simply create a new context like this for every new run.我的解决方案是为每次新运行简单地创建一个这样的新上下文。 Simple but it works.简单但有效。

_dbContext = new DbContext();

I just ran into this issue, and eventually stumbled upon a better solution for those using the typical .NET Core dependency injection.我刚刚遇到了这个问题,最终偶然发现了一个更好的解决方案,适用于那些使用典型的 .NET Core 依赖注入的人。 You can use a scoped DbContext for each operation.您可以为每个操作使用一个作用域 DbContext。 That will reset DbContext.ChangeTracker so that SaveChangesAsync() won't get bogged down checking entities from past iterations.这将重置DbContext.ChangeTracker以便SaveChangesAsync()不会陷入检查过去迭代中的实体。 Here is an example ASP.NET Core Controller method:这是一个示例 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();
    }

Given that ASP.NET Core projects typically use DbContextPool, this doesn't even create/destroy the DbContext objects.鉴于 ASP.NET Core 项目通常使用 DbContextPool,这甚至不会创建/销毁 DbContext 对象。 (In case you were interested, DbContextPool actually calls DbContext.ResetState() and DbContext.Resurrect() , but I wouldn't recommend calling those directly from your code, as they will probably change in future releases.) https://github.com/aspnet/EntityFrameworkCore/blob/v2.2.1/src/EFCore/Internal/DbContextPool.cs#L157 (如果您有兴趣, DbContextPool 实际上调用DbContext.ResetState()DbContext.Resurrect() ,但我不建议直接从您的代码中调用它们,因为它们可能会在未来的版本中发生变化。) https://github .com/aspnet/EntityFrameworkCore/blob/v2.2.1/src/EFCore/Internal/DbContextPool.cs#L157

从.net5.0开始,你可以使用这个: https ://docs.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.changetracking.changetracker.clear?view=efcore-5.0

dbContext.ChangeTracker.Clear();

From EF Core 3.0 there is an internal API that can reset the ChangeTracker.从 EF Core 3.0 开始,有一个内部 API可以重置 ChangeTracker。 Do not use this in production code, I mention it as it may help someone in testing depending on the scenario.不要在生产代码中使用它,我提到它,因为它可能会根据场景帮助某人进行测试。

((IResettableService)ChangeTracker).ResetState();

As the comment on the code says;正如对代码的评论所说;

This is an internal API that supports the Entity Framework Core infrastructure and not subject to the same compatibility standards as public APIs.这是一个支持 Entity Framework Core 基础结构的内部 API,不受与公共 API 相同的兼容性标准的约束。 It may be changed or removed without notice in any release.它可能会在任何版本中更改或删除,恕不另行通知。 You should only use it directly in your code with extreme caution and knowing that doing so can result in application failures when updating to a new Entity Framework Core release.您只应极其谨慎地直接在代码中使用它,并且知道这样做会导致在更新到新的 Entity Framework Core 版本时应用程序失败。

Well my opinion is that, in my experience, EF, or being any orm, does not work well under too much pressure or complex model.好吧,我的观点是,根据我的经验,EF 或作为任何形式,在压力太大或模型复杂的情况下都不能很好地工作。

If you don't want to track, really I would say why even do orm?如果你不想跟踪,我真的会说为什么还要做orm?

If speed is the main force, nothing beats stored procedures and good indexing.如果速度是主要力量,那么没有什么比存储过程和良好的索引更好的了。

And beyond, if your queries are always per id consider using a nosql or perhaps sql with just key and json.除此之外,如果您的查询始终是每个 id,请考虑使用 nosql 或 sql 仅包含 key 和 json。 This would avoid the impedance problem between classes and tables.这将避免类和表之间的阻抗问题。

For your case scenario, loading things in objects that way seems very slow to me.对于您的情况,以这种方式在对象中加载东西对我来说似乎很慢。 Really in your case, stored procedures are better because you avoid the transport of data thru the network, and sql is way faster and optimized to manage aggregation and things like that.确实在您的情况下,存储过程更好,因为您避免了通过网络传输数据,并且 sql 更快并且经过优化以管理聚合等。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在实体框架中将一个实体映射到许多实体? - How do I map one entity to many entities in Entity Framework? 如何序列化实体框架实体(EF 5.0)? - How do I serialize Entity Framework entities (EF 5.0)? 如何在 Entity Framework LINQ To Entities 中进行联合? - How can I do a Union all in Entity Framework LINQ To Entities? 如何使用AutoMapper更新具有嵌套实体的实体,并使用实体框架保存更新的实体? - How do I update an entity with nested entities with AutoMapper and save the updated Entity with Entity Framework? 如何知道 object 是否被 Entity Framework Core 跟踪 - How to know if an object is tracked by Entity Framework Core 如何使用 Entity Framework Core 定义一个实体 class 作为一个集合在多个实体之间共享? - How do I define an entity class to be shared as a collection across multiple entities using Entity Framework Core? 如何使用Entity Framework Core 2.0为X实体创建链接的X实体 - How do I create linked X entities for a X entity using Entity Framework Core 2.0 如何在实体框架中获得带有子实体的实体? - How can i get a entity with sub entities in Entity framework? 如何发布跟踪的实体? - How to release tracked entities? 如何使用实体框架从数据库视图加载相关实体? - How do I load related entities from a database view using entity framework?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM