These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 1 post ] 
Author Message
 Post subject: Problem with transactions?
PostPosted: Tue May 11, 2010 7:28 am 
Newbie

Joined: Fri Apr 30, 2010 6:05 am
Posts: 9
Hi,

I have a strange error which may or may not be related to transactions. Here is my scenario....

I have 2 entities with typical one-to-many parent child relationship. One "Document" can have many "DocumentAudit" objects.

Parent mapping:

Code:
<?xml version="1.0"?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" auto-import="true" assembly="Business">
    <class name="Business.Domain.Document" table="DOCUMENT" lazy="false">
        <id name="Id" type="int" column="DocumentId">
            <generator class="native" />
        </id>
        <property name="FileName" column="FileName" type="string" length="220" />
        <bag name="DocumentAudits" cascade="all" lazy="true" inverse="true">
            <key column="DocumentId" />
            <one-to-many class="Business.Domain.DocumentAudit" />
        </bag>
    </class>
</hibernate-mapping>


And here is the child:

Code:
<?xml version="1.0"?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" auto-import="true" assembly="Business">
    <class name="Business.Domain.DocumentAudit" table="DOCUMENT_AUDIT" lazy="true">
        <cache usage="read-write"/>
        <id name="Id" type="int" column="DocumentAuditId">
            <generator class="native" />
        </id>
        <property name="Action" column="Action" type="string" length="50" />
        <property name="Actor" column="Actor" type="string" length="50" />
        <many-to-one name="Document" class="Business.Domain.Document" fetch="select">
            <column name="DocumentId" unique="true" />
        </many-to-one>
    </class>
</hibernate-mapping>


I have a generic data access class called BaseBroker which has Persist and Delete methods as follows:

Code:
    public void Persist(T obj)
    {
        using (ITransaction txn = nHibernateDB.Session.BeginTransaction())
        {
            try
            {
                nHibernateDB.Session.Persist(obj);
                txn.Commit();
            }
            catch
            {
                txn.Rollback();
                throw;
            }
        }
    }

    public void Delete(T obj)
    {
        using (ITransaction txn = nHibernateDB.Session.BeginTransaction())
        {
            try
            {
                nHibernateDB.Session.Delete(obj);
                txn.Commit();
            }
            catch
            {
                txn.Rollback();
                throw;
            }
        }
    }


All seems OK and I've got some test fixtures covering everyday adding and deleting of objects. All working fine.

HOWEVER, I've run into a very strange error. There is a unique index on the Document.FileName column. I've written a test which needs to verify that attempting to insert a Document with an existing FileName generates the expected exception. So the steps in the test are as follows:


1. Create new Document "doc1" with 1 new DocumentAudit child.
2. Call Persist(doc1)
3. Create new Document "doc2" with 1 new DocumentAudit child, and the SAME FileName as doc1
4. Call Persist(doc2) -> should generate a unique index exception, catch and verify it
5. Cleanup: call Delete(doc1) to delete the first instance that was persisted successfully


What's happening when I run this test is this...it all goes as expected right up to the last step when it tries to clean up and delete doc1. Instead of deleting doc1 I get the following exception:


Test method BusinessTests.Brokers.DocumentBrokerTests.InsertDuplicateFileNameTest threw exception: NHibernate.Exceptions.GenericADOException: could not insert: [Business.Domain.DocumentAudit][SQL: INSERT INTO DOCUMENT_AUDIT (Action, Actor, DocumentId) VALUES (?, ?, ?); select SCOPE_IDENTITY()] ---> System.Data.SqlClient.SqlException: Cannot insert the value NULL into column 'DocumentId', table 'dbo.DOCUMENT_AUDIT'; column does not allow nulls. INSERT fails.
The statement has been terminated..



So I've put some debug into the code (in the form of Console.WriteLine in various places). Look at the Console output (my debug bits start with "==>"):


==> About to create 1st instance
NHibernate: INSERT INTO DOCUMENT (FileName) VALUES (@p0); select SCOPE_IDENTITY();@p0 = 'test.txt'
NHibernate: INSERT INTO DOCUMENT_AUDIT (Action, Actor, DocumentId) VALUES (@p0, @p1, @p2); select SCOPE_IDENTITY();@p0 = 'create', @p1 = 'testuser', @p2 = 39
==> About to create 2nd instance
NHibernate: INSERT INTO DOCUMENT (FileName) VALUES (@p0); select SCOPE_IDENTITY();@p0 = 'test.txt'
==> Caught and handled exception
==> About to delete 1st instance
NHibernate: INSERT INTO DOCUMENT_AUDIT (Action, Actor, DocumentId) VALUES (@p0, @p1, @p2); select SCOPE_IDENTITY();@p0 = 'create', @p1 = 'testuser', @p2 = NULL


So as you can see the bit the generated the error was the last statement - @p2 (the DocumentId) is null.

The bizarre thing is that after the Exception is caught and handled (and the transaction rolled back) the Delete statement should be executed. But it doesn't do that, it's like it's still got a "queue" of SQL statements it needs to execute, as it tries to insert into DOCUMENT_AUDIT!

It's almost like the transaction rollback didn't flush the pending SQL statements???

I hope somebody can help!!

Paul


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 1 post ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.