eConnect transaction not rolling back

Patrick Roth - Click for blog homepageI ran across an interesting case the other day with eConnect.  I had a similar type of case I wrote about previously, but this one is for a completely different reason.

The ISV was moving his working customization from GP 10.0 to GP 2010/2013.

The Problem

Essentially the customization would use eConnect to create a transaction and then also insert/update a custom table with data that goes with the transaction.

To make sure that both the eConnect transaction and the custom data goes in as one unit, the developer is using the SQL TransactionScope pattern.

ISV Code sample that reproduces the problem

using (TransactionScope oTranSc = new TransactionScope(TransactionScopeOption.Required))
{
     //create or update a document calling econnect
     bResult1= eConnect.CreateEntity(txtConnString.Text, myXmlDoc.OuterXml);

     //throw an exception if it failed
    if (!bResult1) throw new Exception();
  
    //call method to update or create our custom data using normal ADO methods
    bResult2 = UpdateCustomData()

    //and throw exception if failed
    if (!bResult2) throw new Exception();

    //if we got here without errors, then complete the scope so that the transactions are committed
    if (bResult1 && bResult2)
    {
    //success so complete the transaction
        oTranSc.Complete();
    }
}
catch
{
   //failure, the transaction will implicitly roll back since the Complete() method wasn't called 
}

I didn't give specifics on the eConnect XML or what the TSQL that the developer uses in the UpdateCustomData() method because it doesn't matter.  

In this case, the ISV found the issue because he mistakenly had the wrong column name in the TSQL.  A SQL Exception was properly thrown and he had expected the eConnect document would have been rolled back - just like it did in 10.0.

So he was very surprised to see that it was not!

I was a bit perplexed since we know that eConnect does indeed roll back a failed transaction and it uses the TransactionScope() method exactly the same way the developer is doing above.  Since ours works OK in eConnect, why doesn't it work when the result of his SQL statement throws an exception?

And of course, why does it work fine in eConnect 10.0?

The Reason Why

The reason is how eConnect 10.0 worked vs eConnect 2010/2013 works.  

In the new versions of eConnect that use the Windows eConnect Service, the "local" call to the eConnect dll actually connects to the eConnect WCF Endpoint the service has created and passes it the connectionstring and XML for the document.

At that point, the eConnect/SQL work is outside of the TransactionScope() defined and so therefore it isn't committed or rolled back in the ISV code.

In 10.0, we used the Enterprise Library under COM+ and so apparently functions "in scope" in the ISV code.

OK, that seems to make sense but is there a solution?

The Solution

The simplest solution that I can think of that is 100% effective is to disable the WCF communication between the 'local' eConnect call and the eConnect WCF service.  Now the transaction is processed locally and we fall within the scope of TransactionScope().

eConnect allows this as an application configuration setting in the app.config file but since we could end up with inconsistent GP/Custom data, changing this in code is the best approach.

The solution is to just add a line to disable the call.

Revised Code

//create or update a customer calling econnect.  Disable the WCF layer first.
eConnect.RequireProxyService = false;
bResult1= eConnect.CreateEntity(txtConnString.Text, myXmlDoc.OuterXml);

//throw an exception if it failed
if (!bResult1) throw new Exception();

 After making this small change, the test exception in the UpdateCustomData() caused the TransactionScope() to implicitly roll back both the failed TSQL and the eConnect transaction.  Success!

Best Regards,

Patrick Roth
Senior Escalation Engineer
GP Developer Support