Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 759787
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 14, 20262026-05-14T15:38:20+00:00 2026-05-14T15:38:20+00:00

In my C# code I am using TransactionScope because I was told not to

  • 0

In my C# code I am using TransactionScope because I was told not to rely that my sql programmers will always use transactions and we are responsible and yada yada.

Having said that

It looks like TransactionScope object Rolls back before the SqlTransaction? Is that possible and if so what is the correct methodology for wrapping a TransactionScope in a transaction.

Here is the sql test

CREATE PROC ThrowError
AS

BEGIN TRANSACTION --SqlTransaction
SELECT 1/0

IF @@ERROR<> 0
BEGIN
  ROLLBACK TRANSACTION --SqlTransaction
  RETURN -1 
END
ELSE
BEGIN
  COMMIT TRANSACTION --SqlTransaction
  RETURN 0
END

go

DECLARE @RESULT INT

EXEC @RESULT = ThrowError

SELECT @RESULT

And if I run this I get just the divide by 0 and return -1

Call from the C# code I get an extra error message

Divide by zero error encountered.
Transaction count after EXECUTE indicates that a COMMIT or ROLLBACK TRANSACTION tatement is missing. Previous count = 1, current count = 0.

If I give the sql transaction a name then

Cannot roll back SqlTransaction.
No transaction or savepoint of that name was found.
Transaction count after EXECUTE indicates that a COMMIT or ROLLBACK
TRANSACTION statement is missing. Previous count = 1, current count = 2.

some times it seems the count goes up, until the app completely exits

The c# is just

        using (TransactionScope scope = new TransactionScope())
        {
             ... Execute Sql 

             scope.Commit()
         }

EDIT:

The sql code has to work for 2000 and 2005

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-14T15:38:21+00:00Added an answer on May 14, 2026 at 3:38 pm

    There was a massive upgrade to the error handling within SQL Server 2005. These articles are fairly extensive: Error Handling in SQL 2005 and Later by Erland Sommarskog and Error Handling in SQL 2000 – a Background by Erland Sommarskog

    The best way is something like this:

    Create your stored procedure like:

    CREATE PROCEDURE YourProcedure
    AS
    BEGIN TRY
        BEGIN TRANSACTION --SqlTransaction
        DECLARE @ReturnValue int
        SET @ReturnValue=NULL
    
        IF (DAY(GETDATE())=1 --logical error
        BEGIN
            SET @ReturnValue=5
            RAISERROR('Error, first day of the month!',16,1) --send control to the BEGIN CATCH block
        END
    
        SELECT 1/0  --actual hard error
    
        COMMIT TRANSACTION --SqlTransaction
        RETURN 0
    
    END TRY
    BEGIN CATCH
        IF XACT_STATE()!=0
        BEGIN
            ROLLBACK TRANSACTION --only rollback if a transaction is in progress
        END
    
        --will echo back the complete original error message to the caller
        --comment out if not needed
        DECLARE @ErrorMessage nvarchar(400), @ErrorNumber int, @ErrorSeverity int, @ErrorState int, @ErrorLine int
    
        SELECT @ErrorMessage = N'Error %d, Line %d, Message: '+ERROR_MESSAGE(),@ErrorNumber = ERROR_NUMBER(),@ErrorSeverity = ERROR_SEVERITY(),@ErrorState = ERROR_STATE(),@ErrorLine = ERROR_LINE()
        RAISERROR (@ErrorMessage, @ErrorSeverity, @ErrorState, @ErrorNumber,@ErrorLine)
    
        RETURN ISNULL(@ReturnValue,1)
    
    END CATCH
    
    GO
    

    however that is only for SQL Server 2005 and up. Without using the TRY-CATCH blocks in SQL Server 2005, you have a very difficult time removing all of the messages that SQL Server sends back. The extra messages you refer to are caused by the nature of how rollbacks are handled using @@trancount:

    from http://www.sommarskog.se/error-handling-I.html#trancount

    @@trancount is a global variable which
    reflects the level of nested
    transactions. Each BEGIN TRANSACTION
    increases @@trancount by 1, and each
    COMMIT TRANSACTION decreases
    @@trancount by 1. Nothing is actually
    committed until @@trancount reaches 0.
    ROLLBACK TRANSACTION rolls back
    everything to the outermost BEGIN
    TRANSACTION (unless you have used the
    fairly exotic SAVE TRANSACTION), and
    forces @@trancount to 0, regards of
    the previous value.

    When you exit a stored procedure, if
    @@trancount does not have the same
    value as it had when the procedure
    commenced execution, SQL Server raises
    error 266. This error is not raised,
    though, if the procedure is called
    from a trigger, directly or
    indirectly. Neither is it raised if
    you are running with SET IMPLICIT
    TRANSACTIONS ON

    If you don’t want to get the warning about the transaction count not matching, you need to only have one transaction open at any one time. You do this by creating all of your procedure like this:

    CREATE PROC YourProcedure
    AS
    DECLARE @SelfTransaction char(1)
    SET @SelfTransaction='N'
    
    IF @@trancount=0
    BEGIN
        SET @SelfTransaction='Y'
        BEGIN TRANSACTION --SqlTransaction
    END
    
    SELECT 1/0
    
    IF @@ERROR<> 0
    BEGIN
        IF @SelfTransaction='Y'
        BEGIN
            ROLLBACK TRANSACTION --SqlTransaction
        END
        RETURN -1 
    END
    ELSE
    BEGIN
        IF @SelfTransaction='Y'
        BEGIN
            COMMIT TRANSACTION --SqlTransaction
        END
        RETURN 0
    END
    
    GO
    

    By doing this, you only issue the transaction commands if you are not already in a transaction. If you code all of your procedures this way, only the procedure or the C# code that issues the BEGIN TRANSACTION will actually issue the COMMIT/ROLLBACK and the transaction counts will always match (you won’t get an error).

    in C# from TransactionScope Class Documentation:

    static public int CreateTransactionScope(
        string connectString1, string connectString2,
        string commandText1, string commandText2)
    {
        // Initialize the return value to zero and create a StringWriter to display results.
        int returnValue = 0;
        System.IO.StringWriter writer = new System.IO.StringWriter();
    
        try
        {
            // Create the TransactionScope to execute the commands, guaranteeing
            // that both commands can commit or roll back as a single unit of work.
            using (TransactionScope scope = new TransactionScope())
            {
                using (SqlConnection connection1 = new SqlConnection(connectString1))
                {
                    // Opening the connection automatically enlists it in the 
                    // TransactionScope as a lightweight transaction.
                    connection1.Open();
    
                    // Create the SqlCommand object and execute the first command.
                    SqlCommand command1 = new SqlCommand(commandText1, connection1);
                    returnValue = command1.ExecuteNonQuery();
                    writer.WriteLine("Rows to be affected by command1: {0}", returnValue);
    
                    // If you get here, this means that command1 succeeded. By nesting
                    // the using block for connection2 inside that of connection1, you
                    // conserve server and network resources as connection2 is opened
                    // only when there is a chance that the transaction can commit.   
                    using (SqlConnection connection2 = new SqlConnection(connectString2))
                    {
                        // The transaction is escalated to a full distributed
                        // transaction when connection2 is opened.
                        connection2.Open();
    
                        // Execute the second command in the second database.
                        returnValue = 0;
                        SqlCommand command2 = new SqlCommand(commandText2, connection2);
                        returnValue = command2.ExecuteNonQuery();
                        writer.WriteLine("Rows to be affected by command2: {0}", returnValue);
                    }
                }
    
                // The Complete method commits the transaction. If an exception has been thrown,
                // Complete is not  called and the transaction is rolled back.
                scope.Complete();
            }
        }
        catch (TransactionAbortedException ex)
        {
            writer.WriteLine("TransactionAbortedException Message: {0}", ex.Message);
        }
        catch (ApplicationException ex)
        {
            writer.WriteLine("ApplicationException Message: {0}", ex.Message);
        }
    
        // Display messages.
        Console.WriteLine(writer.ToString());
    
        return returnValue;
    }
    

    Just a thought, but you might be able to use the TransactionAbortedException catch to get the actual error and ignore the transaction count mismatch warning.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I am validating a zip code using Javascript that is generated server-side, and injected
I recently profiled some code using JVisualVM, and found that one particular method was
Assume the following code: using (SqlConnection conn = new SqlConnection(connectionString)) { ... using (SqlCommand
I have the following code: using System; using System.Linq; using System.Linq.Expressions; public class Program
I have this code :- using (System.Security.Cryptography.SHA256 sha2 = new System.Security.Cryptography.SHA256Managed()) { .. }
The following code using System.Threading; class Test { volatile int counter = 0; public
I have this code: using DC = MV6DataContext; using MV6; // Business Logic Layer
I am trying to dynamicaly compile code using CodeDom. I can load other assemblies,
With the following file reading code: using (FileStream fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read,
I'm messing around with some C code using floats, and I'm getting 1.#INF00, -1.#IND00

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.