我有一个使用EFCore的ASP.NET Core网站。 我想做一些像登录到数据库的工作,但是在将响应发送给用户以便更快地回答之后。
我可以在不同的线程中执行此操作,但由于DbContext的异步访问,我不确定它是否安全。有没有推荐的方法呢?
public async Task<IActionResult> Request([FromForm]RequestViewModel model, string returnUrl = null)
{
try
{
var newModel = new ResponseViewModel(model);
// Some work
return View("RequestView",newModel)
}
finally
{
// Some analysis on the request
// I would like to defer this part
await Log(model);
}
}
其中一个原因是我想调用一个不需要回答的网络服务(地理编码),但是很好地处理日志(我需要坐标的城市/国家)。
答案 0 :(得分:2)
没有开箱即用的方法来做你想做的事。
但是,这是一种可能的方法:
由于工作运行在其他地方,而不是在请求线程上,服务器可以完成请求线程,工作人员可以执行剩下的工作。
答案 1 :(得分:0)
我看到这从未得到解答,但实际上有解决方案。 简单的解决方案:
public async Task<IActionResult> Request([FromForm]RequestViewModel model, string returnUrl = null)
{
try
{
var newModel = new ResponseViewModel(model);
// Some work
return View("RequestView",newModel)
}
finally
{
Response.OnCompleted(async () =>
{
// Do some work here
await Log(model);
});
}
}
安全解决方案(如OnCompleted
曾经在发送响应之前被调用,因此延迟了响应:
public static void OnCompleted2(this HttpResponse resp, Func<Task> callback)
{
resp.OnCompleted(() =>
{
Task.Run(() => { try { callback.Invoke(); } catch {} });
return Task.CompletedTask;
});
}
并致电Response.OnCompleted2(async () => { /* some async work */ })
答案 2 :(得分:0)
以Jeans answer和Ecto.Changeset.cast_assoc(
setting, :data, with: &SettingData.changeset/2
)
模式上的question and answer为基础,可以删除try - return - finally
和try
块(如果您确实不想要捕获异常)。
这导致以下代码:
finally
答案 3 :(得分:-1)
创建一个继承自ActionFilterAttribute
的新类,覆盖OnResultExecuted
方法以执行日志记录,然后将属性类应用于要进行日志记录的控制器操作。
答案 4 :(得分:-1)
尝试使用Hangfire。 Hangfire是在.NET和.NET Core应用程序中执行后台处理的简便方法。无需Windows服务或单独的过程。 以持久存储为后盾。开放和免费用于商业用途。
您可以执行类似
的操作var jobId = BackgroundJob.Enqueue(() => Log(model));
这是我在ASP.NET Core中使用HangFire的blog post