2
votes

I connected the database using Entity Framework. I Implemented a Contact Repository to Save the Contact Information (Sample Repository). In the Said Class file, I declared a static property for handling DBEntities (i.e., BLabsEntities) namely "Context" and also declared a static property for DbContextTransaction.

In the following code I added a try catch block to handle Exceptions of Entity Framework in the SaveContact() Repository method. I Initiated a transaction before starting the Save Contact process in the above said method, then I added a exceptional data into the database table dbo.Contact as per my thought it thrown the exception. In the Catch block I'm initiating the Rollback process of the said transaction and I'm trying to insert the Exception message in the ErrorLog Table, but the Context property holds the Contact information even-though the Rollback process executed. So, it throwing Exception in the catch block once again while on trying to insert the record in the dbo.ErrorLog Table. I added a debugging snapshot for your reference.

C# Code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.Entity;

namespace EF_Sample
{
    public class ContactRepository
    {
        private static BLabsEntities _context;
        private static DbContextTransaction _dbTransaction;

        protected static BLabsEntities Context
        {
            get { return _context ?? (_context = new BLabsEntities()); }
        }

        protected static DbContextTransaction DBTransaction
        {
            get { return _dbTransaction; }
            set { _dbTransaction = value; }
        }

        public void SaveContact(Contact contact = null)
        {
            try
            {
                if (contact == null)
                {
                    contact = new Contact()
                    {
                        FirstName = null,
                        LastName = null
                    };
                }


                BeginTransaction();
                Context.Contacts.Add(contact);
                Context.SaveChanges();
            }
            catch (Exception ex)
            {
                CommitTransaction(false);

                BeginTransaction();
                ErrorLog error = new ErrorLog()
                {
                    Message = ex.Message
                };

                Context.ErrorLogs.Add(error);

                Context.SaveChanges();
            }
            finally
            {
                CommitTransaction();
            }
        }

        private void BeginTransaction()
        {
            DBTransaction = Context.Database.BeginTransaction();
        }

        private void CommitTransaction(bool flag = true)
        {
            try
            {
                if (flag)
                {
                    DBTransaction.Commit();
                }
                else
                {
                    DBTransaction.Rollback();
                }
            }
            catch (Exception Ex)
            {
                Console.WriteLine("Error: {0}", Ex.Message);
            }
        }
    }
}

Debugging Snapshot:

enter image description here

Exception in try Block: Explicitly Created Exception by Code

enter image description here

Exception in Catch Block: Failure of Rollback operation

enter image description here

Database Table Structures:

enter image description here

Kindly assist me how to do the Rollback operation successfully to clear the Context Changes.

1
What exception exactly you get?(I see screen). You get this error when you try add null values, but your db columns cannot be null (not null, lastname,firstname exactly). Also Your repository is little strange. Consider implementing Repository pattern, with generic class and methods. - M. Wiśnicki
@M.Wiśnicki - Obviously. Here I explicitly constructing a Contact object with value NULL to get the exception. Because in my real time implementation, I faced the same issue. So... Please guide me, in this scenario I need to Rollback the transaction and log the Exception Message in the dbo.ErrorLog table - B.Balamanigandan
stackoverflow.com/questions/19520022/… Here you have how get details of this exception, when you call SaveChanges(). Use it and update question. - M. Wiśnicki
@M.Wiśnicki - Yes. In my real implementation I'm updating more than 100 tables in a single call, So I created the Context as a static property. Once all the UPSERT process done, then finally I'm calling the Context.SaveChanges(). In this process if I got any exception, I need to rollback the entire UPSERT. Here I illustrated a simple exception. My issue is Rollback Failure not an Exception. - B.Balamanigandan
Just don't use a static context. That's the root of all troubles. - Gert Arnold

1 Answers

4
votes

The actual answer might be more simple:

https://github.com/aspnet/EntityFramework.Docs/issues/327

The explicit call to dbContextTransaction.Rollback() is in most cases unnecessary, because disposing the transaction at the end of the using block will take care of rolling back.

If an error of sufficient severity occurs in SQL Server, the transaction will get automatically rolled back, and the call to dbContextTransaction.Rollback() in the catch block will actually fail.