views:

46

answers:

3

I am writing a program that uses ADO.NET's SqlCommand to execute a number of user provided batches of T-SQL statements.

My application opens a transaction in which all of the statements are executed to ensure that if there is an error executing any, the whole lot are rolled back.

The problem I have come across is that a badly placed COMMIT (without a matching BEGIN TRAN) in the user provided SQL will commit my all-important transaction and leave me unable to roll back.

Does anybody have any ideas how I can stop the user's SQL from messing with my transaction but still allow them to BEGIN/COMMIT/ROLLBACK their own nested transactions?

+1  A: 

Could you programmatically check each T-SQL statments that get loaded into the SqlCommand for the word COMMIT, so that you could then flag up potential issues with running that T-SQL.

Maybe archive them somewhere to be manually looked at.

kevchadders
This was my initial thought but it would be non-trivial to parse the SQL and still allow nested transaction.
Robert Wood
+5  A: 

The user's SQL needs to be corrected - if it has badly placed COMMITs (or ROLLBACKs), then I'd class that as a bug that needs to be fixed. I don't know much about the specifics of your scenario, but I think this is really what you need to do. If you find yourself trying to implement a workaround, that's when alarm bells should start ringing as it will just make the system more complex/harder to maintain.

AdaTheDev
I'm totally in agreement with this in general - yes the users SQL is the real issue and a workaround is non-ideal. Unfortunately in my scenario I need to be able to tolerate these errors. In an ideal world I would parse the users SQL before executing it (as per @kevchadders' answer) and check for these issues but my feeling is that is too difficult.
Robert Wood
@Robert Wood - I think you'll need to look into Andomar's suggestion. Parsing the SQL could be a can of worms. The only other option I'd suggest is to just carry on as you do now, and log out those that cause a problem.
AdaTheDev
+1  A: 

You could enlist the SqlCommand in a distributed transaction. Those cannot be committed with a COMMIT statement in the database. See the EnlistDistributedTransaction method of the Connection object.

Distributed transactions introduce a whole new class of performance and reliability issues. If you can fix the T-SQL batches like AdaTheDev suggests, that would be a much better option.

Andomar