首页 > 解决方案 > 隔离 EF Core 中的更改

问题描述

以下是我DbContext在 ASP.NET Core Startup 中添加服务的方法:

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

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

A 类 - 方法 1

_dbContext.EntityX.Add(new EntityX { ... });

var product = ClassB.GetProduct(key);

_dbContext.EntityY.Add(new EntityY { Product = product });

_dbContext.SaveChanges();

B 类 - 获取产品

//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)我DbContext在两者中ClassA是否相同ClassB?这有保证吗?

2)如果两者ClassAClassB相同DbContextSaveChangesinClassB会影响EntityX我添加的 inClassA吗?

3) 我应该怎么做才能隔离ClassA和的变化ClassB

标签: c#asp.net-coredependency-injectionentity-framework-core

解决方案


我在和DbContext中都一样吗?这有保证吗?ClassAClassB

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

另一方面,您也可以保证为单独的请求获取单独的数据库上下文。

如果两者ClassAClassB相同DbContext,那么SaveChangesinClassB会影响EntityX我添加的ClassA吗?

对此的简短回答是肯定的。由于它是一个单一的数据库上下文,因此还有一个正在跟踪的实体集合。因此,如果您ClassA.Method1先运行并且那里没有SaveChanges调用,然后运行ClassB.Method2SaveChanges()则后者中的也将保存第一种方法的更改。

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

另一方面,您也可以利用它来发挥自己的优势,并在整个请求处理过程中共享事务,而您的方法并不知道它们是事务的一部分。

我应该怎么做才能隔离ClassA和的变化ClassB

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


推荐阅读