psc*_*hlz 6 c# sqlite entity-framework-core
我有一个服务器客户端架构,其中服务器为客户端提供了一个 Rest API 来同步整个数据库数据。他们将其保存到本地 SQLite 数据库中。该模型位于共享项目中,有时可能会发生变化。因此,客户端需要更新其本地 SQLite 数据库架构。这当然只有在更新客户端软件后才会发生(数据库文件保持不变)。
它只是通过通常删除数据库文件然后重新创建它来实现。
_context.Database.EnsureDeleted();
_context.Database.EnsureCreated();
AttachNewDataFromServerToDatabaseContext(_context);
_context.SaveChanges();
Run Code Online (Sandbox Code Playgroud)
Rest API 服务被实例化为单例并始终使用相同的数据库上下文对象。第一次同步工作正常。但接下来的失败:
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.
Run Code Online (Sandbox Code Playgroud)
因此,尽管整个数据库已被删除,但更改跟踪器仍然知道“旧”实体。
我对此的看法:
你怎么看待这件事?谢谢你的帮助!
- 每次同步数据库时实例化一个新的数据上下文可以修复它,因为更改跟踪器从“零”开始。在我看来不是一个好的解决方案。
我宁愿说这是“正确”的解决方案。Model
默认情况下,上下文元数据(又名)按上下文类型缓存,数据库连接由连接池维护,并且仅在需要时才打开/关闭。所以重用上下文实例的唯一好处是避免创建多个DbSet
实例。
同时,跟踪器会保留很多“实体”实例,并防止它们在SaveChanges
调用后不需要任何垃圾收集。不考虑潜在的多线程访问问题。
所以恕我直言,这是要走的路 - 实例化新的上下文,用它做一些事情并处理它。
- 如果EnsureDeleted 还“重置”更改跟踪器,或者您可以手动进行,那就太好了。
确实那会很棒。但目前EnsureDeleted
,EF Core 和 EF Core都没有提供手动执行此操作的公共方法。
但是有一种内部方式,通常存在可能在未来的某些 EF Core 版本中更改的风险。添加
using Microsoft.EntityFrameworkCore.Infrastructure;
Run Code Online (Sandbox Code Playgroud)
将允许你使用这样的东西
_context.ChangeTracker.GetInfrastructure().ResetState();
Run Code Online (Sandbox Code Playgroud)
大概之前_context.Database.EnsureDeleted();
。这基本上证明您确实应该使用第一个选项(新上下文)。
更新(EF Core 3.0): 即使在内部ChangeTracker
也不再公开StateManager
,所以这里我们需要
using Microsoft.EntityFrameworkCore.Internal;
Run Code Online (Sandbox Code Playgroud)
和分别
_context.GetDependencies().StateManager.ResetState();
Run Code Online (Sandbox Code Playgroud)
以下几行对我有用。参考: https: //github.com/dotnet/efcore/issues/6282
context.ChangeTracker
.Entries()
.ToList()
.ForEach(e => e.State = EntityState.Detached);
context.Database.EnsureDeleted();
context.Database.EnsureCreated();
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
2200 次 |
最近记录: |