我希望能在不创建新上下文的情况下与从外部调用(继承类)的另一个方法共享DB上下文,除非该上下文被处置。我需要检查上下文是否已被处置,以便我可以创建新的上下文。
这是一个rest api。有多个实体的批量上传,我想要共享事务,以便如果其中一个失败,它将不会提交到DB。
这是一个rest api。有多个实体的批量上传,我想要共享事务,以便如果其中一个失败,它将不会提交到DB。
不管有人对设计质量提出质疑,都存在一些情况下dbContext可能处于已释放状态,例如(不完整列表):
例如(在注入的dbContext MVC服务中):
注意:像这样使用dbContext的长时间运行过程应遵循避免dbContext膨胀的良好实践,例如尽可能使用AsNoTracking()方法-因为膨胀可能很快成为一个问题。
性能考虑: 最可靠的选项是在每个子级(api调用/异步任务)上重新创建dbContext,但这可能会产生不必要的性能开销,例如当处理数千个api迭代调用且原子单元事务不可行时。
使用框架测试的解决方案: 实体类型:Microsoft.EntityFrameworkCore.DbContext Version=5.0.16.0, Culture=neutral, PublicKeyToken=adb9793829ddae60
警告: 在使用这种扩展dbContext的方法时有很多警告建议,应该谨慎使用/尽可能避免使用。 详细警告请参见:c-sharp-working-with-entity-framework-in-a-multi-threaded-server
用partial class扩展您的DbContext或将方法添加到您现有的扩展partial class中。
注意:如果仍在使用更新的EntityFrameworkCore库,请评论说明。
public partial class FooDbContext : DbContext
{
// Using Type: 5.0.16.0 EntityFrameworkCore.DbContext (confirm if working with any core library upgrades)
public bool IsDisposed()
{
bool result = true;
var typeDbContext = typeof(DbContext);
var isDisposedTypeField = typeDbContext.GetField("_disposed", BindingFlags.NonPublic | BindingFlags.Instance);
if (isDisposedTypeField != null)
{
result = (bool)isDisposedTypeField.GetValue(this);
}
return result;
}
}
使用方法:
if (fooDbContext == null || fooDbContext.IsDisposed())
{
// Recreate context
}
DbContext
是由DI系统注入的,则您永远不需要自己处理它,因为它只会在控制器的生命周期结束时(即在操作完成之后但在视图呈现之前)被处理。请注意,您永远不应该从控制器操作中返回“打开”的IQueryable<T>
。 - Dai