I am facing a problem that drives me crazy for couple of days now, hoping someone can help me. Here it is ;
I'm using EF4 with oracle database, using dotConnect for oracle from devart as provider. I have wcf service method which calls DeleteCabinet method below;
public void DeleteCabinet(string pRID)
{
using(TransactionScope tranScope = new TransactionScope())
{
DBUtils.DeleteCabinetAndShelves(pRecordId);
//throw exception to test record not deleted
throw new Exception("xxx something has happened test xxx");
tranScope.Complete();
}
}
DBUtils.DeleteCabinetAndShelves looks like below;
public void DeleteCabinetAndShelves(string pRecordId)
{
using(var context = new EdrmEntities())
{
var cabinet = context.Cabinets.Include("Shelves").Single(p => p.RID == pCabinetRID);
//mark all cabinet shelves for deletion
if (cabinet.Shelves != null)
{
foreach (var tempShelf in cabinet.Shelves.ToList())
{
context.DeleteObject(tempShelf);
}
}
//mark cabinet for deletion
context.DeleteObject(cabinet);
//save
context.SaveChanges();
}
}
when I call DeleteCabinet from within my test project, not a wcf call but direct method call, it works OK. It throws exception ,and transaction is rolled back. Thus no record is deleted from DB as expected
The problem is that when I call service method (which calls DeleteCabinet) from a client, the exception is thrown , but the record IS deleted from db. Transaction does not roll back !
seems like calling wcf method does not roll back transaction, but it seems crazy ( at least to me), does anybody know the reason why this might be happening ?
Thanks in advance
EdrmEntities
constructing it's ownEntityConnection
or is it perhaps using a shared connection that has been automatically enlisted in an implicit transaction outside yourTransactionScope
? – Binnacle..class EdrmEntities: ObjectContext { ...
and ctor calls base as followingEdrmEntities():base("name=EdrmEntities", "EdrmEntities")
. Btw how can I understand if shared connection,if used, is enlisted in an implicit transaction outside of my scope ? – PalatinateObjectContext
, using a named connection string (name=EdrmEntities
), then I believe a new connection is opened (not a shared one). I guess the best way to determine if there is an ambient transaction outside yourTransactionScope
is to check theTransaction.Current
property before your new scope is created; automatic transaction enlistment is specific to the configuration of the connection string for your provider (Enlist=false). Hmmm... – BinnacleconnectionString="metadata=res://*/Model.EdrmModel.csdl|res://*/Model.EdrmModel.ssdl|res://*/Model.EdrmModel.msl;provider=Devart.Data.Oracle;provider connection string="User Id=XXX;Password=YYY;Server=ZZZ;Max Pool Size=3000;Pooling=True;Enlist=false;Transaction Scope Local=true""
– PalatinateEnlist=false
in that connection string may be the culprit. I believe that option means that the any connection you create will not enlist itself in the transaction managed by the thread's currentTransactionScope
(orTransaction.Current
). Try changing it toEnlist=true
. – Abaxial