我有一个“已记录”的堆栈,但有一点点更改,我将EFContexts放在接口后面,并且遇到了将所有已知上下文类型注入到ctor中的情况,因此我的DI设置看起来像这样...
services.AddDbContext<MembershipDataContext>(options => options.UseSqlServer(Config.Connections["Membership"]));
services.AddDbContext<CoreDataContext>(options => options.UseSqlServer(Config.Connections["Core"]));
services.AddDbContext<B2BDataContext>(options => options.UseSqlServer(Config.Connections["B2B"]));
services.AddScoped<IMembershipDataContext, MembershipDataContext>();
services.AddScoped<ICoreDataContext, CoreDataContext>();
services.AddScoped<IB2BDataContext, B2BDataContext>();
services.AddScoped<IEnumerable<IDataContext>>(i => new IDataContext[] { i.GetService<MembershipDataContext>(), i.GetService<CoreDataContext>(), i.GetService<B2BDataContext>() });
我的理解是,对于一个HTTP请求,当我在多个地方请求其中的任何一个时,我会得到相同的实例,逻辑是这样的……
A => B => ICoreDataContext
A => IEnumerable<IDataContext>
...应该给A和B相同的CoreDataContext实例,因此当B从数据库中提取某些实体并且A调用SaveChangesAsync()时,这应该不是问题。
尽管如此,我似乎还是得到了这个例外...
The instance of entity type 'User' cannot be tracked because another instance with the same key value for {'Id'} is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached. Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see the conflicting key values.
...当我对多个表执行复杂的操作并且父对象(在本示例中为A)尝试调用保存更改时。
是从EF的2个不同父对象中“获取”对象的实例,而是从同一上下文实例中“获取”一个对象的行为吗?
我的代码实际上在做什么...
因为C没有得到任何帮助,这是不允许的吗? 我的理解是,所谓的SaveChanges无关紧要,因为我应该只与我交互的CoreDataContext实例(共享),并且在整个过程中只进行了1次保存调用。
答案 0 :(得分:-1)
在获取用户并保存用户时是否使用异步操作?如果是这样,您可能正在尝试执行EF Core不支持的并行操作。
https://docs.microsoft.com/en-us/ef/core/miscellaneous/configuring-dbcontext
部分:
避免DbContext线程问题
解释您在小节中看到的奇怪行为:
忘记在等待异步操作完成之前 在同一DbContext上启动其他任何操作
如果无法检测到并发访问,则可能导致未定义 行为,应用程序崩溃和数据损坏。
在您的情况下,当您尝试将A保存到B中时可能尚未完成获取操作(反之亦然)。尝试同步进行操作,看看是否发现相同的问题,我认为您不应该这样做。