views:

148

answers:

0

Hi,

I would like to implement an application wide retry system for all entity SaveChanges method calls.

Technologies:
Entity framework 4.0
.Net 4.0

namespace Sample.Data.Store.Entities {  
    public partial class StoreDB  
    {  
        public override int SaveChanges(System.Data.Objects.SaveOptions options)
        {            
            for (Int32 attempt = 1; ; )
            {

                try
                {
                    return base.SaveChanges(options);
                }
                catch (SqlException sqlException)
                {
                    // Increment Trys
                    attempt++;

                    // Find Maximum Trys
                    Int32 maxRetryCount = 5;

                    // Throw Error if we have reach the maximum number of retries
                  if (attempt == maxRetryCount)
                      throw;

                  // Determine if we should retry or abort.
                  if (!RetryLitmus(sqlException))
                      throw;
                  else
                      Thread.Sleep(ConnectionRetryWaitSeconds(attempt));
              }
          }
      }

      static Int32 ConnectionRetryWaitSeconds(Int32 attempt)
      {
          Int32 connectionRetryWaitSeconds = 2000;

          // Backoff Throttling
          connectionRetryWaitSeconds = connectionRetryWaitSeconds *
              (Int32)Math.Pow(2, attempt);

          return (connectionRetryWaitSeconds);
      }



      /// <summary>
      /// Determine from the exception if the execution
      /// of the connection should Be attempted again
      /// </summary>
      /// <param name="exception">Generic Exception</param>
      /// <returns>True if a a retry is needed, false if not</returns>
      static Boolean RetryLitmus(SqlException sqlException)
      {
         switch (sqlException.Number)
          {
              // The service has encountered an error
              // processing your request. Please try again.
              // Error code %d.
              case 40197:
              // The service is currently busy. Retry
              // the request after 10 seconds. Code: %d.
              case 40501:
              //A transport-level error has occurred when
              // receiving results from the server. (provider:
              // TCP Provider, error: 0 - An established connection
              // was aborted by the software in your host machine.)
              case 10053:
                  return (true);
          }

          return (false);
      }
  }   
}

The problem:

How can I run the StoreDB.SaveChanges to retry on a new DB context after an error occured? Something simular to Detach/Attach might come in handy.

Thanks in advance! Bart