gpt4 book ai didi

c# - 如何使用 SQLite 使用 EF Core 删除整个数据库并重置更改跟踪器

转载 作者:行者123 更新时间:2023-12-01 22:43:50 39 4
gpt4 key购买 nike

我有一个服务器客户端架构,其中服务器为客户端提供Rest API来同步整个数据库数据。他们将其保存到本地 SQLite 数据库中。该模型位于共享项目中,有时可能会发生变化。因此,客户端需要更新其本地 SQLite 数据库架构。当然这只有在更新客户端软件后才会发生(数据库文件保持不变)。

通常通过删除数据库文件并随后重新创建它来简单地实现。

_context.Database.EnsureDeleted();
_context.Database.EnsureCreated();

AttachNewDataFromServerToDatabaseContext(_context);

_context.SaveChanges();

Rest API 服务被实例化为 singleton,并始终使用相同的数据库上下文对象。第一次同步工作正常。但接下来的失败了:

System.InvalidOperationException: The instance of entity type '***' cannot be tracked because another instance with the key value '{id:  ***}' is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached.

因此,尽管整个数据库已被删除,但更改跟踪器仍然知道“旧”实体。

我的想法:

  • 每次同步数据库时实例化一个新的数据上下文可以解决此问题,因为更改跟踪器从“零”开始。在我看来这不是一个好的解决方案。
  • 如果 EnsureDeleted 也能“重置”更改跟踪器,那就太好了,或者您也可以手动执行此操作。

你对此有何看法?感谢您的帮助!

最佳答案

  • Instantiating a new data context every time the database is synchronized could fix it because the Change Tracker starts at "zero" then. Not a good solution in my eyes.

我宁愿说这是“正确”的解决方案。默认情况下,上下文元数据(又名模型)按上下文类型进行缓存,数据库连接由连接池维护,并且仅在需要时才打开/关闭。因此,重用上下文实例的唯一好处是避免创建多个 DbSet 实例。

同时,跟踪器将保留大量“实体”实例,并防止它们在 SaveChanges 调用后被垃圾回收,而无需进行任何操作。不计算潜在的多线程访问问题。

所以恕我直言,这就是要走的路 - 实例化新上下文,用它做一些事情并处理它。

  • Would be great if EnsureDeleted also "resets" the Change Tracker or you could do it manually.

确实,那太好了。但目前 EnsureDeleted 都没有这样做,EF Core 也没有提供公共(public)手动执行此操作的方法。

不过,有一种内部方法,通常存在可能在未来的某个 EF Core 版本中更改的风险。添加

using Microsoft.EntityFrameworkCore.Infrastructure;

允许你使用这样的东西

_context.ChangeTracker.GetInfrastructure().ResetState();

可能在_context.Database.EnsureDeleted();之前。这基本上证明您确实应该使用第一个选项(新上下文)。

更新(EF Core 3.0): ChangeTracker 即使在内部也不再公开 StateManager,所以这里我们需要

using Microsoft.EntityFrameworkCore.Internal;

和分别

_context.GetDependencies().StateManager.ResetState();

更新(EF Core 5.0):感谢Vaclav Elias在注释中,现在 ChangeTracker 公开了一个 Clear() 方法来清除所有跟踪实体的 DbContext。

_context.ChangeTracker.Clear();

关于c# - 如何使用 SQLite 使用 EF Core 删除整个数据库并重置更改跟踪器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55454624/

39 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com