gpt4 book ai didi

c# - 在 Web api/MVC 中使用异步 Controller 处理的 Entity Framework

转载 作者:行者123 更新时间:2023-12-04 03:19:43 27 4
gpt4 key购买 nike

我有这个小代码示例:

public class ValueController : ApiController
{
private EstateContext _db;

public ValueController()
{
_db = new EstateContext();
}

[HttpPost]
public async void DoStuff(string id)
{
var entity = await _db.Estates.FindAsync(id); //now our method goes out and Dispose method is calling
//returns here after disposing
_db.SaveChanges(); // _db is disposed

}

protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
_db.Dispose();
}
}

每个 ApiController/Controller 都实现了 IDisposable 接口(interface)。因此,在 Dispose 方法中,我想释放任何资源,例如 DbContext。但是如果使用异步,这个 Dispose 方法会在第一次出现 await 时调用。所以在等待之后我已经处理了 DbContext 。
那么在使用异步时处理 EF 上下文的最佳方法是什么?原来不能依赖 Controller 中的 Dispose 方法?

最佳答案

But if async is used, this Dispose method calls at first occurrence of await.



@Konstantins answer是正确的,但请允许我详细说明为什么会发生这种情况。当您使用 async void方法,您基本上是在为您的方法调用创建一个“即发即弃”语义,因为此方法的任何调用者本身都不能使用 await 异步等待它, 因为它返回 void而不是一种可等待的形式(例如 Task )。

因此,尽管 WebAPI 确实支持异步方法,但在调用您的操作时,它似乎是同步的 void返回方法,然后 ASP.NET 运行时继续处理您的 Controller ,因为它假定您已完成操作。

当暴露一个 TaskTask<T> ,你明确地告诉调用者“听着,这个方法是异步的,将来最终会返回一个值”。 ASP.NET 运行时知道您的 Controller 还没有完成调用他的 Action ,并等待 Action 的实际完成。

这就是为什么这样的调用:
[HttpPost]
public async Task DoStuffAsync(string id)
{
var entity = await _db.Estates.FindAsync(id);
_db.SaveChanges();
}

作品。

作为旁注 - EF DbContext应尽快使用和处置。将它们用作多个操作的全局变量是个坏主意,因为它们不是 线程安全 任何一个。我会建议一种不同的模式,其中每个操作都会初始化和处理 DbContext :
[HttpPost]
public async Task DoStuffAsync(string id)
{
using (var db = new EstateContext())
{
var entity = await db.Estates.FindAsync(id);
db.SaveChanges();
}
}

正如@Wachburn 在评论中指出的那样,这种方法确实不太可测试。如果您确保在每个操作完成后释放您的 Controller 和操作并且没有重复使用上下文,您可以安全地注入(inject) DbContext通过 DI 容器。

关于c# - 在 Web api/MVC 中使用异步 Controller 处理的 Entity Framework ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35988090/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com