我看到所有答案都有其自身的意义,而且都是正确的。所以,我只能对它们做一些澄清。
您应该根据暴露对象的方式选择处理对象的时刻。例如,您的原始代码隐含地将MpaContext db 暴露给AspNet 管道,并且在netcore 完成他的工作之前,您不能处置db。因此,正如您所提到的,您可以通过Response.RegisterForDispose() 注册处置它。但是,这并不常见,因为您通常无法访问 Response - 您只能在 Controller 中执行此操作,或者与 Controller 依赖项共享它,但这会增加代码复杂性。
这就是为什么您可以通过依赖控制器的生命周期来避免这种情况。因为,它在请求范围内,它将一直存在,直到发送响应。因此,您可以创建 db 作为控制器依赖项并将其保存在属性中。你也应该在控制器上实现IDisposable。
public class RoleController : IDisposable
{
private MpaContext DbContext { get; }
public RoleController()
{
DbContext = new MpaContext();
}
[HttpGet( "ViewerRoles" )]
public IAsyncEnumerable<ViewerRole> GetViewList()
{
return DbContext.ViewerRoles.AsAsyncEnumerable();
}
public void Dispose()
{
DbContext.Dispose();
}
}
在这种情况下,即使您将逻辑移至其他类(我相信它应该如此),您也可以坚持这种模式。但是,如果您手动创建一次性对象,您应该关心处理它们。这就是 DI 提供帮助的时刻。
通过使用 DI,您可以忘记处置由 DI 创建的对象。 DI 将在其生命周期结束时对任何依赖项调用 Dispose()。如果您使用MpaContext 下的EntityFramework,请调用AddDbContextPool<MpaContext>() 或AddDbContext<MpaContext>() 注册您的MpaContext。通过这种方法,您将获得控制器的清晰代码。
public class RoleController
{
private MpaContext DbContext { get; }
public RoleController( MpaContext dbContext )
{
DbContext = dbContext;
}
[HttpGet( "ViewerRoles" )]
public IAsyncEnumerable<ViewerRole> GetViewList()
{
return DbContext.ViewerRoles.AsAsyncEnumerable();
}
}
如果您不想将MpaContext 暴露给控制器并想在GetViewList() 中手动创建它,您仍然可以在操作方法中枚举结果并按照Theodor Zoulias 的回答处理上下文。但是,如果您可以简单地将这项工作委托给 DI,您为什么要这样做。