简体   繁体   中英

SQL Server 2008 R2 Express and nightly C# database update job needs to “rollback” entire database on failure

I have a C# program that will run nightly. It reads in records from flat files and does many different inserts and updates to a SQL Server database depending on the contents of each record.

Despite using transaction blocks and Try...Catch in stored procedures, and Try...Catch in C#, I really need these updates to be all or nothing.

I cannot take snapshots of db since we are using SQL Server 2008 R2 Express edition.

Can anyone please explain a good method (if there is one) for returning the SQL Server database to the state it was in before the nightly C# job ran, if the C# program catches an error? Basically, if the C# program catches an error, I want it to stop running, and I want to "rollback" the database to before the C# program did any changes. I need this to be an automated solution, not a manual restore from a backup.

In a sense, I want a Transaction block around the C# program that could rollback everything the C# program did.

The database is in Multi_User mode with a full recovery model (with nightly scheduled db and log backups). There is a web app tied to this database, but end users should really never have need to access this web app in the middle of the night.

I have searched everywhere for solutions, but no luck. Perhaps not using right keywords.

I look forward to feedback.

Thanks in advance, David

I've gotten around this in the past by reading the file, inserting into a staging table, and then calling a single stored procedure to to the actual inserts into the production tables from the staging table.

If there is an error reading the file, truncate the staging table (or use an import identifier of some sort). If there is an error in the data, it should be easy to know that on the stored procedure side and easy to use one or two set based operations wrapped in a transaction.

This has the added benefit of being able to look at the data easily in the staging table if there was a data issue, possibly manually fixing it, and running the import stored procedure again.

I'm sorry, but that's what I thought database transactions were for. First you connect to the database, next you start a database transaction, and then you use the same connection & transaction for every operation:

using ( SqlConnection conn = new SqlConnection( . . . ) ) {
    using ( SqlTransaction tran = new conn.BeginTransaction() ) {
        try {
            // Data processing operation #1
            using ( SqlCommand command = new SqlCommand( ". . .", conn, tran ) {
                // Your processing code here
            }

            // Repeat the pattern used for Data Processing Operation #1 for all other operations

            // Commit the transaction if everything completed without error.
            tran.Commit();
        } catch ( SqlException ) {
            // An error occurred.  Roll the transaction back.
            tran.Rollback();

            // Other error handling code if needed.
        }
    }
}

Since there's only one transaction, everything is rolled back to the initial state if anything goes wrong. If you need to cancel the operation for other reasons, you call tran.Rollback() & return. This is exactly why transactions were invented; I don't understand why they won't do the job for you.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM