4

In my asp.net core web application, I am logging the exceptions to the database.Till now everything works fine but problem is that when the DbConext.SaveChanges in try block throws an exception, cannot log the exception to the database as DbConext.SaveChanges in catch block also throws the same exception.

Here is the code I have tried so far :

try
{
    _unitOfWork.Repository<Product>().InsertEntity(product);
     await _unitOfWork.SaveChangesAsync();//This throws exception due the model validation failure
}
catch (Exception exception)
{
    ExceptionModel exceptionModel = new ExceptionModel();
    using (MyDbContext dbContext = new MyDbContext())
    {
        await dbContext.ExceptionModels.AddAsync(exceptionModel);
        await dbContext.SaveChangesAsync(); // Throws the same exception that was thrown in try block due to entity framework transaction
    }
}

Note: I guess the problem is causing due to the Entity Framework transaction.

Please help how can I overcome this situation to log the exception to the database. Thanks!

10
  • 2
    If only you told us the details about those exceptions... Commented Feb 20, 2018 at 8:28
  • 1
    Let's say you failed to save changes to a database because the database server is down. Now you want to log something to the database to indicate that the first save failed. What do you expect to happen? Commented Feb 20, 2018 at 8:30
  • 1
    What was the exact exception thrown? Commented Feb 20, 2018 at 8:39
  • 1
    Use some external service such as Exceptionless and don't do try/catch. Logging db errors into the same db sounds like a bad idea. Commented Feb 20, 2018 at 9:33
  • 1
    ELMAH Commented Feb 20, 2018 at 16:12

3 Answers 3

2

In try block you are adding some changes to db context. While saving you got some exception and using the same db context in catch block to log that exception. Here the db context still has unsaved changes made in try block. So you will get the same exception while saving the context.

To avoid this you have to discard the changes from db context in catch block before adding more changes.

private void ResetContextState() => _context.ChangeTracker.Entries()
.Where(e => e.Entity != null && e.state == EntityState.Added).ToList()
.ForEach(e => e.State = EntityState.Detached);

Edit: the above code worked for me.

Sign up to request clarification or add additional context in comments.

Comments

2

In all versions of Entity Framework, whenever you execute SaveChanges() to insert, update or delete on the database, the framework will wrap the operation in a transaction. This transaction lasts long enough to execute the operation and then commits.

this is all I did after catching a sql exception on SaveChangesAsync and it works great in core 6. I was able to create a new log record and insert it using the same context after just one line which detaches all entities. They are still there in error state so that is why you can't continue without detaching.

_context.ChangeTracker.Clear();

Comments

1

In Entity framework Core, I have solved the problem easily using EF-Core Transaction

try
{
    _unitOfWork.Repository<Product>().InsertEntity(product);
     await _unitOfWork.SaveChangesAsync();//This throws exception due the model validation failure
}
catch (Exception exception)
{
    ExceptionModel exceptionModel = new ExceptionModel();

    string connectionString = _configuration.GetConnectionString("MyConnection");

    var options = new DbContextOptionsBuilder<MyDbContext>()
                .UseSqlServer(new SqlConnection(connectionString))
                .Options;

    using (var dbContext = new MyDbContext(options))
    {
         using (var transaction = dbContext.Database.BeginTransaction())
         {
             try
             {
                   dbContext.Exceptions.Add(exceptionModel);
                   await dbContext.SaveChangesAsync();
                   transaction.Commit();
             }
             catch (Exception e)
             {
                 Console.WriteLine(e);
                 throw;
             }
         }
     }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.