PDA

View Full Version : Transaction only partially rolling back?


Chris Coleman
06-27-2007, 02:51 PM
Hi,

With the business object code below I would have expected that no objects be persisted to the database:


[Transaction()]
public long UploadAttachment(long commentId, string filename, Stream data)
{
//Persist changes to the DB
AttachmentDO attachment = new AttachmentDO();
attachment.FileName = serverFileName;
attachment.DisplayName = filename;
attachment = _AttachmentDAO.Save(attachment);

CommentDO comment = _CommentDAO.Get(commentId, true);
comment.Attachments.Add(attachment);
_CommentDAO.SaveOrUpdate(comment);

throw new OperationFailedException("FORCED ROLLBACK");

return attachment.Id;
}


What I am seeing is the attachment entry being persisted to the database, but not the join to the comments_attachments table.

Is this the expected behaviour?

If I remove the [Transaction()] attribute then changes are made to both ojects so it seems that it is working to some respect? This is the case if I use TransactionProxyFactoryObject's or the attribute driven method.

Below are some of the logs from the relevant section, with the Hibernate show_sql output in place too:

2007-06-27 14:44:18,194 [11] INFO Eurocom.Core.WCFServiceBase.WCFServiceBaseType [(null)] - Started sesssion for 'christopherc', [guid=urn:uuid:cb601d9f-6064-4c5d-b9a6-9ecd3f44cd91]
2007-06-27 14:44:18,256 [11] DEBUG Spring.Data.NHibernate.SessionFactoryUtils [(null)] - Opening Hibernate Session
2007-06-27 14:44:18,256 [11] DEBUG Spring.Data.NHibernate.SessionFactoryUtils [(null)] - Registering Spring transaction synchronization for new Hibernate Session
2007-06-27 14:44:18,256 [11] DEBUG Spring.Data.NHibernate.HibernateTemplate [(null)] - Found thread-bound Session for HibernateTemplate
NHibernate: INSERT INTO bugs.attachments (displayname, filename) VALUES (:p0, :p1); select lastval(); :p0 = 'splash-blue.bmp', :p1 = '000000000017070627144418'
2007-06-27 14:44:18,288 [11] DEBUG Spring.Data.NHibernate.HibernateTemplate [(null)] - Not closing pre-bound Hibernate Session after HibernateTemplate
2007-06-27 14:44:18,288 [11] DEBUG Spring.Data.NHibernate.SessionFactoryUtils [(null)] - Opening Hibernate Session
2007-06-27 14:44:18,288 [11] DEBUG Spring.Data.NHibernate.SessionFactoryUtils [(null)] - Registering Spring transaction synchronization for new Hibernate Session
2007-06-27 14:44:18,288 [11] INFO NHibernate.Loader.Loader [(null)] - SELECT commentdo0_.id as id36_0_, commentdo0_.versionid as versionid36_0_, commentdo0_.content as content36_0_, commentdo0_.createdon as createdon36_0_, commentdo0_.createdbyid as createdb5_36_0_, commentdo0_.changedon as changedon36_0_, commentdo0_.changedbyid as changedb7_36_0_, commentdo0_.isremoved as isremoved36_0_ FROM bugs.comments commentdo0_ WHERE commentdo0_.id=:p0 for update
NHibernate: SELECT commentdo0_.id as id36_0_, commentdo0_.versionid as versionid 36_0_, commentdo0_.content as content36_0_, commentdo0_.createdon as createdon36_0_, commentdo0_.createdbyid as createdb5_36_0_, commentdo0_.changedon as changedon36_0_, commentdo0_.changedbyid as changedb7_36_0_, commentdo0_.isremoved as isremoved36_0_ FROM bugs.comments commentdo0_ WHERE commentdo0_.id=:p0 for update; :p0 = '17'
2007-06-27 14:44:18,303 [11] INFO NHibernate.Loader.Loader [(null)] - SELECT attachment0_.commentid as commentid__1_, attachment0_.attachmentid as attachme2_1_, attachment1_.id as id18_0_, attachment1_.displayname as displayn2_18_0_, attachment1_.filename as filename18_0_ FROM bugs.comments_attachments attachment0_ left outer join bugs.attachments attachment1_ on attachment0_.attachmentid=attachment1_.id WHERE attachment0_.commentid=:p0
NHibernate: SELECT attachment0_.commentid as commentid__1_, attachment0_.attachmentid as attachme2_1_, attachment1_.id as id18_0_, attachment1_.displayname as displayn2_18_0_, attachment1_.filename as filename18_0_ FROM bugs.comments_attachments attachment0_ left outer join bugs.attachments attachment1_ on attachment0_.attachmentid=attachment1_.id WHERE attachment0_.commentid=:p0; :p0 = '17'
2007-06-27 14:44:18,319 [11] DEBUG Spring.Data.NHibernate.HibernateTemplate [(null)] - Found thread-bound Session for HibernateTemplate
2007-06-27 14:44:18,319 [11] DEBUG Spring.Data.NHibernate.HibernateTemplate [(null)] - Not closing pre-bound Hibernate Session after HibernateTemplate
2007-06-27 14:44:18,335 [11] DEBUG Spring.Data.NHibernate.SessionFactoryUtils [(null)] - Closing Hibernate Session
2007-06-27 14:44:18,366 [16] INFO Eurocom.Core.WCFServiceBase.WCFServiceBaseType [(null)] - Session stopped for 'christopherc', [guid=urn:uuid:cb601d9f-6064-4c5d-b9a6-9ecd3f44cd91]


Cheers
Chris

Chris Coleman
06-27-2007, 03:11 PM
Ah - Ok...

I have just figured out the cause...

Something about the implementation of the 'Changable session factory' discussed in the thread below is causing the issue. http://forum.springframework.net/showthread.php?t=2722.

I shall look into it more - however I can't help but feel there must be a better design than needing to alter the session factory at runtime.

I shall investigate and post back here with any findings.

Thanks - and apologies for the fuss.

Cheers
Chris

Mark Pollack
06-27-2007, 06:27 PM
Hi,

Having re-read the posts you are using your 'ChangeableSessionFactory ' and associated classes because you need to change the database mappings at runtime? What is the specific use case? The situation you are describing certainly works with the standard out of the box NHibernate integration so I'm not sure what is going on. The log file is only showing some selects, not inserts.

Is your case the same as on this post (http://forum.hibernate.org/viewtopic.php?t=976049) in the NHibernate forums? That seems like a good solution. There is also a similar class for Spring.NET DbProvider abstraction, Spring.Data.MultiDelegatingDbProvider located in the Spring.Data.Integration.Tests.2005 project. If the NH ConnectionProvider and the Spring.NET DbProvider share the same lookup mechanism, then you could even mix ADO.NET/NH operations as well.

In anycase, some lower level switching maybe more appropriate. Another alternative is to use a HotSwappableTargetSource (http://www.springframework.net/doc-1.1-M1/reference/html/aop.html#aop-ts-swap), but I don't know if that would meet your needs.

Cheers,
Mark