TransactionScope doesn't rollback on exception

TransactionScope doesn't rollback on exception

Old forum URL: forums.lhotka.net/forums/t/11832.aspx


mmedic posted on Tuesday, February 12, 2013

I have a BO (Country) with a child BO (State) which also has a child BO (City). When I update the parent BO (Country), add a child State and run save, when an exception occurs in the DAL (on purpose), the transaction is not rolled back. I am using SqlCE. I am attaching a sample stripped down project that demonstrates the issue. What am I doing wrong?

JonnyBee replied on Wednesday, February 13, 2013

You use your DalManager in faulty ways.

The DalManager (and the ConnectionManager) relies on reference counting to determine when close the actual connection.

Your rules are not making sure to dispose the DalManager and hence the dalManager and reference counting is off. Resulting in the update happening on a connection that was created and opened in one of the Fetch operations and is therefore not be enlisted in the TransactionScope on the Update method.

See: http://msdn.microsoft.com/en-us/library/bb896149%28v=sql.100%29.aspx

You must change all your rules, ex

was:

        protected override void Execute(RuleContext context)
        {
            var name = (string)context.InputPropertyValues[_nameProperty];
            var id = (int)context.InputPropertyValues[_idProperty];
            var dal = DalFactory.GetManager();
            var countryDal = dal.GetProvider<ICountryDal>();
            var exists = countryDal.Exists(id, name);
            if (exists)
            {
                context.AddErrorResult("Country with the same name already exists in the database.");
            }
        }

DalManager is IDisposable but is not explicitly disposed here so it depends on when the GC will actually collect the object.

Should be:

        protected override void Execute(RuleContext context)
        {
            var name = (string)context.InputPropertyValues[_nameProperty];
            var id = (int)context.InputPropertyValues[_idProperty];
            using (var dal = DalFactory.GetManager())
            {
                var countryDal = dal.GetProvider<ICountryDal>();
                var exists = countryDal.Exists(id, name);
                if (exists)
                {
                    context.AddErrorResult("Country with the same name already exists in the database.");
                }
            }
        }

Once you correct your rules the update will rollback as expected.

If you experience this behavior - make sure to check the reference count in the ConnectionManager when
you enter a DataPortal_XYZ method. It should always start at 1 the first time.

Copyright (c) Marimer LLC