I want to capture the error from entity framework.
So i have the below code
return await _context.SaveChangesAsync(cancellationToken);
if something goes wrong in the above code i want it to be captured as a warning in database, but as of now it is automatically saving in the database as error which has to be warning actually.
below is the error that i get
An exception occurred in the database while saving changes for context type 'ValuationsReporting.Models.ValuationsReportingContext'. System.InvalidOperationException: The property 'TemplateTypeId' on entity type 'ValuationFundTemplate' has a temporary value. Either set a permanent value explicitly or ensure that the database is configured to generate values for this property. at Microsoft.EntityFrameworkCore.Update.Internal.CommandBatchPreparer.Validate(ModificationCommand modificationCommand) at Microsoft.EntityFrameworkCore.Update.Internal.CommandBatchPreparer.BatchCommands(IReadOnlyList
1 entries)+MoveNext() at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.ExecuteAsync(DbContext _, ValueTuple
2 parameters, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.Storage.ExecutionStrategy.ExecuteImplementationAsync[TState,TResult](Func4 operation, Func
4 verifySucceeded, TState state, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.Storage.ExecutionStrategy.ExecuteImplementationAsync[TState,TResult](Func4 operation, Func
4 verifySucceeded, TState state, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(IReadOnlyList`1 entriesToSave, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync(Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)System.InvalidOperationException
Microsoft.EntityFrameworkCore.Update
I tried using try catch but as soon as it goes to that line the error is logged in database.
Actual code :
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);
}
Agreed with the @PrashantPimpale you can simply use try catch
.
But for the advanced approach, I would suggest you can use a Global Error Handling Middleware.
Through which you can capture any error occurred in the whole dotnet
API/Application.
Just and Elaboration below:
// 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>();
}
}
Then add app.UseErrorHandlingMiddleware();
in the Startup's Configure()
method.
You have to first create a ErrorHandlingMiddleware
class.
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.
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With