C# 隔离EF核心的变化

C# 隔离EF核心的变化,c#,asp.net-core,dependency-injection,entity-framework-core,C#,Asp.net Core,Dependency Injection,Entity Framework Core,下面是我如何在ASP.NET核心启动中添加DbContext服务的: services.AddDbContextPool<AppDbContext>(options => options.UseMySql(Configuration.GetConnectionString("DefaultConnection"))); services.AddScoped<ClassA, ClassA>(); services.AddScoped<C

下面是我如何在ASP.NET核心启动中添加
DbContext
服务的:

services.AddDbContextPool<AppDbContext>(options =>
            options.UseMySql(Configuration.GetConnectionString("DefaultConnection")));

services.AddScoped<ClassA, ClassA>();
services.AddScoped<ClassB, ClassB>();
ClassB-GetProduct

//Check product if it exists in the database
//Else, get details of the product from a Web API

var newProduct = new Product{ ... }
_dbContext.Products.Add(newProduct );

_dbContext.SaveChanges();

return newProduct;
老实说,我还并没有试过运行这个程序,为了简洁起见,这些代码是真实代码的精简版

我的问题是:

1) 我在
ClassA
ClassB
中是否有相同的
DbContext
?这能保证吗

2) 如果
ClassA
ClassB
具有相同的
DbContext
,则
ClassB
中的
SaveChanges
是否会影响
ClassA
中添加的
EntityX

3) 我应该如何隔离
ClassA
ClassB
中的更改

我在
ClassA
ClassB
中是否有相同的
DbContext
?这能保证吗

数据库上下文注册为作用域依赖项,这意味着在处理单个传入请求期间共享实例。每个请求都将获得自己的依赖项注入范围,因此在单个请求中,可以保证获得相同的数据库上下文实例

另一方面,还保证为单独的请求获取单独的数据库上下文

如果
ClassA
ClassB
具有相同的
DbContext
,则
ClassB
中的
SaveChanges
是否会影响
ClassA
中添加的
EntityX

对此的简短回答是肯定的。因为它是一个单一的数据库上下文,所以也有一个被跟踪的实体集合。因此,如果您先运行
ClassA.Method1
,但没有在那里调用
SaveChanges
,然后运行
ClassB.Method2
,后者中的
SaveChanges()
也会保存第一个方法的更改

虽然这听起来可能有问题,但实际上通常不是:请求通常作为控制器操作的一部分处理,因此有一个非常清晰的控制流。因此,不存在任何并行处理,只要在使用上下文后始终“清理”上下文(例如,通过调用
SaveChanges()
),就不会有问题

另一方面,您也可以利用这一点,在处理请求的整个过程中共享事务,而无需您的方法知道它们是事务的一部分

我应该如何隔离
ClassA
ClassB
中的更改


想想你是否真的需要隔离。
Method2
影响
Method1
的唯一方式是
Method1
对未保存的实体执行更改。如果你这样做,那么你很可能滥用了你的实体。通常,一个方法应该在实体上完成它的工作,而不留下脏状态。

虽然这听起来可能有问题,但实际上通常不是:1。使用异步(“并行”)执行时出现问题。2.将出现问题,因为您开始构建依赖于某个功能的逻辑,该功能共享上下文,这将使逻辑和代码在一段时间后难以遵循。@Fabio(1)Asynchronous!=平行的如果你在处理一个请求时同时做一些事情,那么无论如何你都会有其他的问题和事情需要记住。(2) 我说你应该在使用上下文后进行清理,所以不,你不依赖于该功能。对不起,我不清楚。我试着在引号中使用“parallel”。我的意思是,异步将提供几乎同时运行查询的可能性(不是并行运行,仍然在同一个线程上),但两个查询的异步执行时间将少于一个接一个查询。如果没有对设置进行“黑客”操作,则无法使用作用域为DbContext的。另一个警告是,当您决定在
IHostedService
中使用作用域DbContext时,您将无法在该服务中使用它。3。当两个不同的类将通过使用
Attach(新实体{Id=Id,Property=new value})
更新同一实体时,您将在使用
Attach
之前检查DbContext中是否已经存在实体。很抱歉,我的主要观点是:使用临时DbContext将使您的生活更简单。最好在可能的情况下为每个查询创建新的上下文(使用
using
语句),这样您就可以完全自由地在代码中使用不同的技术方法。
//Check product if it exists in the database
//Else, get details of the product from a Web API

var newProduct = new Product{ ... }
_dbContext.Products.Add(newProduct );

_dbContext.SaveChanges();

return newProduct;