raiserror from trigger different result for insert / update

Posts   
 
    
mdissel
User
Posts: 92
Joined: 16-Sep-2003
# Posted on: 11-Apr-2008 13:28:54   

I've got a table has a trigger that does a check for duplicates. If a duplicate is found a RaiseRror is returned and the transaction is rollbacked (in the trigger)

        IF (EXISTS (...))
        BEGIN
            RAISERROR('...', 10, 1)
            ROLLBACK TRAN
        END

When i've an existing entity and call save, an ORMConcurrencyException is raised if the trigger has done a rollback of the transaction

When i've a new entity and call save, save returns false, but no exception is raised...

I've checked the sql statements with insert/update using profiler, in both cases the transaction is rollbacked in the database (sql2000)

Why is this behaviour different between insert / update??

ps. i'm using the 1.0.2005.1 (latest release) and self-servicing.. (older project flushed )

Thanks

Marco

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 11-Apr-2008 17:34:00   

Inserts don't throw ORMConcurrencyExceptions as there's nothing for concurrency to check: they're new rows, so they're not UPDATING an existing row. That's what concurrency is all about: multiple updates / deletes on the same row. Inserts is a different matter in this: there's always a single insert.

btw, rollbacks of transactions inside the db could lead to 'zombie' transactions in .net: the ADO.NET transaction object doesn't get a signal from the db that the transaction has been rolledback.

Frans Bouma | Lead developer LLBLGen Pro
mdissel
User
Posts: 92
Joined: 16-Sep-2003
# Posted on: 11-Apr-2008 19:45:11   

Otis wrote:

Inserts don't throw ORMConcurrencyExceptions as there's nothing for concurrency to check: they're new rows, so they're not UPDATING an existing row. That's what concurrency is all about: multiple updates / deletes on the same row. Inserts is a different matter in this: there's always a single insert.

Yes, but there's no exception raised at all.. I expected an exception even on an insert, because of the raiserror instruction in the trigger..

Otis wrote:

btw, rollbacks of transactions inside the db could lead to 'zombie' transactions in .net: the ADO.NET transaction object doesn't get a signal from the db that the transaction has been rolledback.

raiserror is enough? rollback tran is not necessary?

Thanks Marco

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 11-Apr-2008 20:37:44   

mdissel wrote:

Otis wrote:

Inserts don't throw ORMConcurrencyExceptions as there's nothing for concurrency to check: they're new rows, so they're not UPDATING an existing row. That's what concurrency is all about: multiple updates / deletes on the same row. Inserts is a different matter in this: there's always a single insert.

Yes, but there's no exception raised at all.. I expected an exception even on an insert, because of the raiserror instruction in the trigger..

Hmm... Well, all exceptions thrown by the ADO.NET provider are wrapped, so if it reaches .net code, it is wrapped. Perhaps the severity level you specified isn't enough? You should use a severity level of 11 or higher ('Handling Errors and messages in applications, sqlserver 2005 BOL')

Otis wrote:

btw, rollbacks of transactions inside the db could lead to 'zombie' transactions in .net: the ADO.NET transaction object doesn't get a signal from the db that the transaction has been rolledback.

raiserror is enough? rollback tran is not necessary? Thanks Marco

The transaction is also rolled back in .NET code. So if you roll back a transaction inside the trigger, raise an error which results in an exception, the transaction is also rolled back there, which leads to an exception if the transaction is already rolled back.

However, if the update/insert was a single statement and no transaction was necessary, the rollback is required. You can test this with @@TRANCOUNT. If it's 0, the trigger is executed inside an implicit transaction (insert /update statement's own transaction) and you should rollback. if it's > 0, a BEGIN TRANS has been called and you should NOT rollback

Still it's odd that there's no error reported...

Frans Bouma | Lead developer LLBLGen Pro
mdissel
User
Posts: 92
Joined: 16-Sep-2003
# Posted on: 11-Apr-2008 20:52:02   

Otis wrote:

Still it's odd that there's no error reported...

Yes, that's what made me think the code inside the trigger is correct, i don't have a ready to use testmethod, but if you want to reproduce this, i did creat an explicit transaction in my testcode (and using sql server 2000)

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 12-Apr-2008 10:06:10   

Checking the code, it seems v1.0.2005.1 doesn't wrap any db exceptions (that feature was introduced in v2), it just bubbles them upwards. If it detects a concurrency voilation it will thrown an concurrency exception itself (when 0 rows were affected). So if you dont get ANY exception bubbled upwards, it's not thrown. Try upping the severity level to 11 as I described above.

Frans Bouma | Lead developer LLBLGen Pro