C# 如何捕获EF异常

C# 如何捕获EF异常,c#,asp.net-core,C#,Asp.net Core,我想从实体框架中捕获错误 所以我有下面的代码 return await _context.SaveChangesAsync(cancellationToken); 如果上面的代码出现错误,我希望它在数据库中被捕获为警告,但现在它会自动在数据库中保存为错误,实际上它必须是警告 下面是我得到的错误 保存上下文更改时数据库中发生异常 键入“ValuationReporting.Models.ValuationReportingContext”。 System.InvalidOperationExc

我想从实体框架中捕获错误

所以我有下面的代码

 return await _context.SaveChangesAsync(cancellationToken);
如果上面的代码出现错误,我希望它在数据库中被捕获为警告,但现在它会自动在数据库中保存为错误,实际上它必须是警告

下面是我得到的错误

保存上下文更改时数据库中发生异常 键入“ValuationReporting.Models.ValuationReportingContext”。 System.InvalidOperationException:上的属性“TemplateTypeId” 实体类型“ValuationFundTemplate”具有临时值。任何一套 永久值,或确保已配置数据库 为该属性生成值。在 Microsoft.EntityFrameworkCore.Update.Internal.CommandBatchPreparer.ValidateModificationCommand 修改命令位于 Microsoft.EntityFrameworkCore.Update.Internal.CommandBatchPreparer.BatchCommandSiredOnlyList 1 条目+移动下一步 Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.ExecuteAsyncDbContext _,ValueTuple2参数,CancellationToken CancellationToken位于 Microsoft.EntityFrameworkCore.Storage.ExecutionStrategy.ExecuteImplementationAsync[TState,TResult]函数4 操作,Func4验证成功,TState,CancellationToken 取消令牌在 Microsoft.EntityFrameworkCore.Storage.ExecutionStrategy.ExecuteImplementationAsync[TState,TResult]函数4 操作,Func4验证成功,TState,CancellationToken 取消令牌在 Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesSyncirReadOnlyList`1 entriesToSave,CancellationToken CancellationToken位于 Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesSyncBoolean acceptAllChangesOnSuccess,CancellationToken CancellationToken位于 Microsoft.EntityFrameworkCore.DbContext.SaveChangesSyncBoolean 接受更改成功,取消令牌取消令牌

System.InvalidOperationException异常

Microsoft.EntityFrameworkCore.Update

我尝试使用try-catch,但当它到达该行时,错误就会记录到数据库中

实际代码:

try
                {
                    foreach (var template in snapshotDto.SnapshopFundTemplateDtos)
                    {
                        if (template.FundId != null)
                        {
                            foreach (var fundId in template.FundId)
                            {
                                var tempTemplate = allFundTemplates.Where(x => x.ValuationId == valuation.Id && x.FundId == fundId && x.TemplateTypeId == template.TemplateTypeId).FirstOrDefault();

                                //var tempTemplate = await _valuationFundTemplateRepository.GetOne(valuation.Id, fundId, template.TemplateTypeId, true, cancellationToken);
                                if (tempTemplate == null)
                                {
                                    tempTemplate = new ValuationFundTemplate();
                                    tempTemplate.CreatedBy = _userRepository.claimsPrincipal.Identity.Name;
                                    tempTemplate.CreatedOn = DateTime.Now.ToUniversalTime();
                                    isTemplateUpdate = false;
                                }
                                //tempTemplate.IsDeleted = false;
                                //if (template.IsDeleted)
                                //{
                                //     _valuationFundTemplateRepository.Delete(tempTemplate);
                                //}
                                //else
                                //{
                                //tempTemplate.IsDeleted = template.IsDeleted;

                                tempTemplate.IsDeleted = false;
                                tempTemplate.IsDefaultFundTemplate = template.IsDefault;
                                tempTemplate.FundId = fundId;
                                tempTemplate.ValuationId = valuation.Id;
                                tempTemplate.TemplateTypeId = 0;
                                tempTemplate.TemplateId = template.TemplateId;
                                tempTemplate.ModifiedBy = _userRepository.claimsPrincipal.Identity.Name;
                                tempTemplate.ModifiedOn = DateTime.Now.ToUniversalTime();
                                tempTemplates.Add(tempTemplate);
                                if (isTemplateUpdate)
                                {
                                    _valuationFundTemplateRepository.Update(tempTemplate);
                                }
                                else
                                {
                                    await _valuationFundTemplateRepository.Insert(tempTemplate, cancellationToken);
                                }
                                //  }

                                await _valuationFundTemplateRepository.SaveAsync(cancellationToken);//here is where the error occurs which i dont want to capture in database.
                                if (!isTemplateUpdate)
                                    valuation.ValuationFundTemplate.Add(tempTemplate);
                            }

                        }
                    }
                }catch(Exception e)
                {
                    var z = e.Message;
                }



public virtual async Task<int> SaveAsync(CancellationToken cancellationToken = default(CancellationToken))
        {
            return await _context.SaveChangesAsync(cancellationToken);
        }

同意@PrashantPimpale,您只需使用try-catch即可

但是对于高级方法,我建议您可以使用全局错误处理中间件。 通过它,您可以捕获整个dotnetapi/应用程序中发生的任何错误

以下是公正和详细阐述:

// Extension method used to add the middleware to the HTTP request pipeline.
    public static class ErrorHandlingMiddlewareExtensions
    {
        public static IApplicationBuilder UseErrorHandlingMiddleware(this IApplicationBuilder builder)
        {
            return builder.UseMiddleware<ErrorHandlingMiddleware>();
        }
    }

@PrashantPimpale我已经尝试使用try-catch,但错误仍然记录在数据库中无法取消-错误记录在数据库中?你能解释一下吗?@PrashantPimpale我试过下面的代码试试{return await\u context.savechangessynccancellationtoken;}catchException e{var z1=e.Message;return 0;}不过,在捕获块之前,它会被记录为数据库中的错误。数据库中已发生错误的日志记录。但我不想在数据库中记录一个特定的错误。您也可以分享您的代码吗。这将非常有用。我想您还必须在SaveAsync方法中添加try-catch,然后在异常块中抛出错误。仅供参考:正在生成错误,因为您没有将更新的实体设置为修改状态。entity.EntryUpdateUser.State=EntityState.Modified;我知道这个错误是如何产生的。实际上,我也尝试过将try-catch放在save-async方法中,但在此之前,错误仍然会记录在数据库中。
 public class ErrorHandlingMiddleware
    {
        private readonly RequestDelegate _next;

        public ErrorHandlingMiddleware(RequestDelegate next)
        {
            _next = next;
        }

        public async Task Invoke(HttpContext httpContext)
        {
            try
            {
                await _next(httpContext);
            }
            catch (Exception ex)
            {
                await HandleExceptionAsync(httpContext, ex);
            }
        }

        private static async Task HandleExceptionAsync(HttpContext context, Exception exception)
        {
          // Implement how you want to handle the error.
        }
}