C# 隔离EF核心的变化
下面是我如何在ASP.NET核心启动中添加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
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;