ASP.NET 2.0, SQL 2005. I have a very basic insert statement. I enter all the data into the app and step through. No errors are rasied in the app or the stored proc. Yet, when I go to check out the table, no record was inserted. Is there some sort of quirk or bug in SQL server I am unaware of? I have tried ExecuteScalar & ExecuteNonQuery.
Can it be that you open a transaction and never Commit one? Remember that
using(var transaction = connection.BeginTransaction())
{
// Code
}
does not commit it, but rather rolls back the whole thing. You have to explicitly invoke transaction.Commit().
You need to commit your transaction.
I had (have) this problem on a website of mine written in PHP. If you are trying to insert a string are you sure you have escaped all necessary characters? Using a single quote in something like don't, won't, or aren't needs to be escaped!
Related
I am using a C# class that is calling a SQL stored procedure in a serializable transaction.
So if something goes wrong in the stored procedure, everything is rolled back.
I have one statement in the SQL stored procedure that should be always executed (even if the stored procedure fails at some point and a rollback occurs). The statement is an update of a record.
I cannot change the C# library, so I need to do this in my stored procedure.
Is there some way I can execute that one statement outside the transaction?
You could perhaps use SAVE TRANSACTION. It is not supported in distributed transactions, and your statement must be executed first, so it might not be what you are looking for.
I have found the solution.
I didn't realize that SQL knew it was called in a transactional matter by the c# class.
The update statement that should always be executed is the first step (and also last step) in the procedure. Let me clarify:
I have an IF function. If it is true, the update should occur no matter what. If it is false, some transactional logic should be executed.
Now in the c# class, it expects a result from the stored proc. If the proc doesn't return a result (like it does in the update statement), it rollbacks the transaction.
So by just adding the following lines right after the update statement, the update occurs :)
IF ##TRANCOUNT > 0
BEGIN
COMMIT TRANSACTION
END
Your solution does not sound like a good one.. For example- if your stored procedure will be part of bigger transaction, then it will commit all changes made before it. Also I believe no one would guess that your proc has such behaviour without first seeing code.
The need to always execute some part of proc sounds like need for security audit. So maybe you should use trace, extended events or sql server audit instead.
if you really need what you say you need- you can use method described here: How to create an autonomous transaction in SQL Server 2008
We have a developer connecting to SQL Server using pymssql which uses freetds. His script dynamically generates sql insert queries based on values in a MySQL DB.
The statements are parsed properly and have proper begin transaction/commits in them when you view them in SQL Profiler. The only 'user error message' that comes up a 'changed database context to...' which comes up whenever you issue a USE in SQL. After the batch completes, there is a transaction log event 'rollback' and all the records that were inserted are removed.
We are not using XACT_ABORT_OFF because I haven't seen 'change db context to' be affected by it.
Does anyone have any ideas or experience with this? Thanks!
[edit]:
The code copied out of profiler works fine in SSMS using the same user and there are no triggers.
[2nd edit]:
inside SQL profiler I see a 'TransactionLog' entry with 'rollback' under eventsubtype, however there isn't a TM:Rollback Tran
Perhaps the connection is not being committed or closed correctly. Check the freetds documentation to ensure that you are using the correct usage patterns. Also you might want to check whether its possible to enable autocommit mode on the connection.
So after much searching and triple checking the auto commit setting, we caught that 2 variables were very closely named and it was committing the wrong one. There is a mysql and a pymysql module, but in this case we were using pymssql but it was typed in at pymysql instead. Thanks everyone who commented.
We have a .NET application (VB / VS2010) and are calling many stored procedures on a SQL Server 2008 for database queries. We also have quite a few update/insert/delete triggers that are executed automatically once these stored procedures modify the database tables.
There are quite often situations when a stored procedure is called and it seems to perform ok as no error is raised and the .NET app continues as usual. However if I then look under the covers and perform the stored procedure call manually via SQL Server Client I see that a trigger that's executed right after the stored procedure fails, thus rolling back all changes.
So my question is: what's the best way to detect and pass through errors in our .NET --> stored procedure --> trigger scenario to know for sure in the .NET app that everything succeeded or not in case of an error?
Many thanks in advance,
Steve
Update: I am at home now and away from my desk (and the code base) for the weekend, so won't have a chance to check the very details of the stored procedures. Thanks so much for the answers given so far. I can have a look at the code again next week.
But in the meantime...
One question was about the version of MS SQL Server: it's 2008.
From what I know out of the top of my head we are calling the stored procedures (at least those that don't read data and "just" update, delete or insert data) in this manner:
Using connection As New SqlConnection("connectionString")
Dim command As New SqlCommand("EXEC STORED_PROCEDUR_ENAME), connection)
command.Connection.Open()
command.ExecuteNonQuery()
End Using
I think the assumption behind the code above is the expectation that if something fails within the stored procedure or a related trigger, that
command.ExecuteNonQuery()
would then fail. That might be my first problem, i.e. will I have to alter this code?
One question below was if I use ExecuteDataReader, so the answer is no, at least not so far...
I'll comment on the SQL specific questions and suggestions below.
I actually had the same issue today,
to solve it i used an output #msg and placed it after each function in the sproc.
SET #msg = 'Test print 1'
each section i added one so i know what ever the last number printed was where the sproc failed. I then went to the table where the trigger was failing and adjusted it until it printed the last number and passed.
You should check ##error after each statement, and return the error if one exists.
Here's a good article for you. Check out the section "Why is My Error Not Raised". It describes a scenario that could be your problem.
http://www.sommarskog.se/error-handling-II.html
You might also want to try turning XACT_ABORT on, so stored procedures would fail for most errors.
EDIT: Here's another link that might help explain this.
http://www.novicksoftware.com/tipsandtricks/tips-erorr-handling-in-a-stored-procedure.htm
You can either return an error from your procedure if you check ##error and find it != 0, or you can use RAISERROR, which will definitely result in an exception in calling code.
http://msdn.microsoft.com/en-us/library/ms178592.aspx
as you mention that you are using sql server 2008. this gives capacity to use try.. catch. here is the article.
http://msdn.microsoft.com/en-us/library/ms175976.aspx
Also look at this forum.
http://social.msdn.microsoft.com/Forums/eu/transactsql/thread/03eae70e-d478-44a7-90f3-8e1d27d9f22e
i think try..catch will do the job. also in .net side i would use following code.
try
{
// your stored procedure execution code.
}
Catch (sqlexception e)
{
// do something with sql exception.
}
try this scenario see if that solves your issue.
I've got a simple bit of code that uses BeginTransaction(). The resulting transaction is assigned to the connection that I'm using for some sql commands.
When I profile the resulting sql, I don't see a BEGIN TRANSACTION at any point. What might be happening that would prevent the transaction from being used?
Transactions are handled at a lower level when using ADO.NET. There are no "BEGIN TRANSACTION" statements sent to the server.
You need to ensure that you not only set the transaction on the connection object, but you also need to assign the transaction into the sqlCommand.
See this codeproject article for an example.
To reiterate Philippe's statement:
Transactions are handled at a lower level when using ADO.NET. There are no "BEGIN TRANSACTION" statements sent to the server.
At some point SQL has to be converted into actual calls. Most ADO.NET (all that I've worked with) often send a database specific command to BEGIN, COMMIT, and ROLLBACK transactions as sending ASCII (or whatever else) would be less efficient than something the server will have to parse.
This is why sending parameterised queries are often faster than pure SQL based ones as the library can send specific commands which results in less parsing and probably less data validation (?).
HTH!
I've a feeling this might not be possible, but here goes...
I've got a table that has an insert trigger on it. When data is inserted into this table the trigger fires and parses a long varbinary column. This trigger performs some operations on the binary data and writes several entries into a second table.
What I have recently discovered is that sometimes the binarydata is not "correct" (i.e. it does not conform to the spec it is supposed to - I have NO control over this whatsoever) and this can cause casting errors etc.
My initial reaction was to wrap things in TRY/CATCH blocks, but it appears this is not a solution either, as the execution of the CATCH means the transaction is doomed and I get a "Transaction doomed in trigger" error.
What is imperitive is that the data still gets written to the initial table. I don't care if the data gets written to the second table or not.
I'm not sure if I can accomplish this or not, and would gratefully receive any advice.
what you could do is commit a transaction inside a trigger and then perform those cast.
i don't know if that's a possible solution to your problem though.
another option would be to create a function IsYourBinaryValueOK which would check the column value. however the check would have to be done with like to not cause an error.
It doesn't sound like this code should run in an insert trigger since it is conceptually two different transactions. You would probably be better off with asynchronous processing such as service broker, a background nanny task that looks for 'not done' work, etc. You could also handle it by using a sproc to do the insert in one transaction and then having it call the do-other-work code afterwards.
If you absolutely have to do it in the trigger then you basically need an autonomous transaction. For some ideas see this link (the techniques apply to sql 2005 as well).