多个异步函数中使用.Net EF Core DbContext.Save()

3
我被DbContext.SaveChanges()困扰。根据文档,SaveChanges()应该保存对数据库所做的所有更改。
考虑这种情况:我有多个异步函数,它们都针对不同的表格。如果所有函数都尝试创建新条目,但由于计算处理等原因,有些函数比其他函数需要更长时间,那么第一个到达DbContext.SaveChanges()的函数是否会保存其他异步函数所做出的所有更改,无论这些函数是否已到达SaveChanges部分?
因此,我的担忧是在多个异步函数中,在业务流之前数据将被保存,只因为另一个函数说了SaveChanges()。
这是否属实,它们是否为每个异步函数创建了一些内部事务范围?
Startup.cs可以在此处找到:https://github.com/drakoumel/DatacircleAPI/blob/master/Startup.cs

3
如果你指的是在多个线程中使用相同的dbContext实例,并且甚至并行执行多个SaveChanges操作 - 不要那样做。永远不要从多个线程使用相同的上下文 - 为每个并行操作创建一个单独的上下文。 - Evk
我有一个Web API,在启动期间创建了一个DbContext,但我不知道每次调用控制器操作时是否使用相同的连接。 - czioutas
请展示你的代码,特别是如何注入/使用DbContext。我同意@Evk的观点。如果以正确的方式注入DBContext,你不应该有任何问题。每个DbContext实例中都会自动创建事务,因此为每个线程创建一个新实例非常重要 - 实际上,如果你在每个线程中注入DBContext,则会自动完成这项工作。 - Lukasz Mk
这就是我所说的 - 不要那样做,不要在启动时创建它。每当需要时创建新的上下文实例,执行所需操作,必要时调用SaveChanges。 - Evk
非常抱歉,我忘记添加存储库链接了。您可以查看Startup.cs,然后查看Database / ApplicationDbContext.cs中的EF模型等初始化,以及任何存储库中所注入的DbContext。 - czioutas
1个回答

3
为了理解所有这些行为,您需要知道您的上下文和存储库在 DI 容器中是如何注册以及使用哪些生命周期进行注册。
上下文的注册方式如下:
services.AddDbContext<ApplicationDbContext>(options => options.UseMySql(Configuration["ConnectionStrings:DefaultConnection"]));

如果您查看AddDbContext方法的参数,您会发现它有一个contextLifetime参数,默认值为ServiceLifetime.Scoped。因此,上下文是使用Scoped生命周期注册的。

存储库被注册为

services.AddScoped<IDatasourceRepository, DatasourceRepository>();

关于Scoped生命周期的解释。

Scoped生命周期指的是当在DI容器中解析时,每个请求都会创建一个新对象。因此,您现在知道每个请求都有一个单独的存储库和上下文实例,因此控制器操作的不同调用使用不同的上下文实例,以便它们的SaveChanges不会相互干扰。


啊,我不知道AddDbContext默认是Scoped。非常感谢你! - czioutas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接