CJ *_*ten 2 c# entity-framework-core .net-core
我有一个 ASP Core 3.1 Web 项目,我想向其中添加 EntityFramework Core。
我创建了一个数据库上下文,即具有数据库操作的模型类,并将其注入到我的主类(Azure Bot)中。
但是,当我尝试将记录插入数据库时,它总是失败并出现错误
System.Threading.Tasks.TaskCanceledException:“任务已取消。”
这是我的startup.cs:
services.AddDbContext<IVRContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection"),
optionBuilder => optionBuilder.EnableRetryOnFailure()
)
);
services.AddTransient<IVRCallModel>();
Run Code Online (Sandbox Code Playgroud)
这是我正在调用的 IVRModel 中的函数:
public async Task InsertCallAsync(IVRCall call)
{
try
{
await _ivrContext.Calls.AddAsync(call);
await _ivrContext.SaveChangesAsync();
}
catch (Exception ex)
{
throw new Exception(ex.Message, ex);
}
}
Run Code Online (Sandbox Code Playgroud)
我就是这样称呼它的:
private async Task NotificationProcessor_OnNotificationReceivedAsync(NotificationEventArgs args)
{
this.GraphLogger.CorrelationId = args.ScenarioId;
if (args.ResourceData is Call call)
{
if (call.Direction != CallDirection.Outgoing && call.ToneInfo == null)
{
if (args.ChangeType == ChangeType.Created && call.State == CallState.Incoming)
{
await SaveCall(call.Id, call.CallChainId, "Incoming");
.... code removed
}
}
}
}
private async Task SaveCall(string callId, string callChainId, string callState, string redirectCallId = null)
{
IVRCall newCall = new IVRCall();
newCall.Id = callId;
newCall.CallChainId = callChainId;
newCall.TimeStamp = DateTime.Now.ToString("dd-MM-yyyy HH:mm:ss");
newCall.State = callState;
newCall.RedirectCallId = redirectCallId;
await _ivrCallModel.InsertCallAsync(newCall);
}
Run Code Online (Sandbox Code Playgroud)
编辑:“原始”NoticicationProcessor_OnNotificationReceived 函数,它调用异步方法。(来自微软示例项目)
private void NotificationProcessor_OnNotificationReceived(NotificationEventArgs args)
{
_ = NotificationProcessor_OnNotificationReceivedAsync(args).ForgetAndLogExceptionAsync(this.GraphLogger, $"Error processing notification {args.Notification.ResourceUrl} with scenario {args.ScenarioId}");
}
Run Code Online (Sandbox Code Playgroud)
当代码在响应已发送到客户端后尝试运行时,就会发生该异常。当您使用 async/await 时,当某处未等待某些异步内容时,可能会发生这种情况。
事实上,这就是发生在这里:
private void NotificationProcessor_OnNotificationReceived(NotificationEventArgs args)
{
_ = NotificationProcessor_OnNotificationReceivedAsync(args).ForgetAndLogExceptionAsync(this.GraphLogger, $"Error processing notification {args.Notification.ResourceUrl} with scenario {args.ScenarioId}");
}
Run Code Online (Sandbox Code Playgroud)
await当作用于一个不完整的对象时Task,它实际上会返回。它返回Task自己的 a ,以便调用者可以跟踪它何时完成。因此,当NotificationProcessor_OnNotificationReceivedAsync返回时,工作实际上尚未完成。由于您没有使用Task,因此执行会继续,并且 ASP.NET 会打包请求并结束该请求的任务。
将事件处理程序与异步代码一起使用可能会很棘手,特别是在这种情况下,您需要暂停执行直到工作完成,否则您会得到意外的结果。您可以使用类似的方法同步等待异步代码.GetAwaiter().GetResult(),但这可能会产生意想不到的后果。
我认为最好的选择是在这种情况下只使用同步代码:使用.SaveChanges()而不是.SaveChangesAsync().
关于您对 的使用.AddAsync(),文档说:
此方法是异步的,仅允许特殊值生成器(例如“Microsoft.EntityFrameworkCore.Metadata.SqlServerValueGenerationStrategy.SequenceHiLo”使用的生成器)异步访问数据库。对于所有其他情况,应使用非异步方法。
.Add()所以无论如何你应该一直使用,即使在异步方法中也是如此。
try关于您的/块的评论catch也是有效的。如果您要捕获一个异常只是为了使用相同的消息抛出一个新异常,那么根本不要捕获该异常。即使您需要在再次抛出异常之前进行一些日志记录或其他操作,也请使用 justthrow;而不是throw new Exception(ex.Message, ex);. 引发新的异常会更改异常发生位置的堆栈跟踪,并使调试变得困难。
| 归档时间: |
|
| 查看次数: |
9640 次 |
| 最近记录: |