2016-02-25 27 views
9

Veritabanı çağrılarıma (C# ve veritabanına erişmek için Microsoft teknolojisini kullanarak) bir 'geçici' özel durumuyla yeniden deneme yapmak için bazı sarıcı kodu yazmak istiyorum. Geçici olarak, sonunda (asla işe yaramayacak mantıksal hatalara karşı) çözülecek iyi bir şansın olduğu bir şey kastediyorum. Aklıma gelen Örnekler:Sql Sunucu Geçici İstisna Numaraları

  • Kilitlenme Bunları noktaya SQLException hatası numaralarını kullanarak planlıyordu

  • Bağlantı Zaman Aşımı
  • Komut zaman aşımı. Örneğin Yani:

    List<RunStoredProcedureResultType> resultSet = null; 
    int limit = 3; 
    for (int i = 0; i < limit; ++i) 
    { 
        bool isLast = i == limit - 1; 
        try 
        { 
         using (var db = /* ... */) 
         { 
          resultSet = db.RunStoredProcedure(param1, param2).ToList(); 
         } 
         //if it gets here it was successful 
         break; 
        } 
        catch (SqlException ex) 
        { 
         if (isLast) 
         { 
          //3 transient errors in a row. So just kill it 
          throw; 
         } 
         switch (ex.Number) 
         { 
          case 1205: //deadlock 
          case -2: //timeout (command timeout?) 
          case 11: //timeout (connection timeout?) 
           // do nothing - continue the loop 
           break; 
          default: 
           //a non-transient error. Just throw the exception on 
           throw; 
         } 
        } 
        Thread.Sleep(TimeSpan.FromSeconds(1)); //some kind of delay - might not use Sleep 
    } 
    return resultSet; 
    

    -

    Yani anahtar soru (. buglar için afedersiniz Sadece anında ben de fark olduğunu yazdık ben ... o kadar güzel sarabilirdiniz) : “geçici” olarak hangi sayıları dikkate almalıyım (geçici olduğunu düşündüğüm şeyin diğer insanların geçtiğini düşündüğünün farkına varabilirim).

    https://msdn.microsoft.com/en-us/library/cc645603.aspx

    ama muazzam ve çok kullanışlı not: Burada güzel bir liste buldum. Başkaları benzer bir şey için kullandıkları bir liste oluşturdu mu? Sonunda

    GÜNCELLEME, biz 'kötü listeye' seçti - genellikle programcı hatalardır - Hata bilinen 'olmayan geçici hatalar' listesinin bir biriyse. Cevap olarak kullandığımız numaraların bir listesini ekledim.

  • +1

    Benzer bir şey yaptık. "kurtarılabilir istisnalar" denir. bağlantı hataları, zaman aşımları ve kilitlenme de dahil olmak üzere. ancak: üç kez aramayı tekrarladığınızda kilitlenme süresinin uzaması muhtemeldir - değişken gecikme veya başka kilitlenme çözümleme yöntemleri eklemeyi düşünün. ve iki kez yeniden denemeye başladığınızda aşırı yüklenme nedeniyle bir bağlantı zaman aşımı da daha da kötüleşebilir. – dlatikay

    +0

    Oh evet, bir gecikme planlamıştım. Teşekkürler @dlatikay - Yukarıdaki – thab

    +0

    güncelleştirecektir Merhaba, bir öneri için soruyorsun, ne yazık ki, herhangi bir programcı sizin durumunuz için yararlı olacağını farklı bir fikir olabilir çünkü çözülebilir bir soru değildir, bu yüzden şu anda redacted yolu ile konu dışı; Saygılarımızla. – jclozano

    cevap

    2

    Kendi sorumu cevapladığım için özür dilerim, ancak birileri hala ilgilenirse, kendi hata kodları listemizi oluşturmaya başladık. İdeal değil, ama bunun çok sık olmamalı olduğunu düşündük.

    Soruda belirtildiği gibi 'iyi liste' yerine 'hatalı liste' yaklaşımını seçtik. şu ana kadar elimizde kimlikleri şunlardır: Biz fark

    PARAMETER_NOT_SUPPLIED = 201; 
    CANNOT_INSERT_NULL_INTO_NON_NULL = 515; 
    FOREGIN_KEY_VIOLATION = 547; 
    PRIMARY_KEY_VIOLATION = 2627; 
    MEMORY_ALLOCATION_FAILED = 4846; 
    ERROR_CONVERTING_NUMERIC_TO_DECIMAL = 8114; 
    TOO_MANY_ARGUMENTS = 8144; 
    ARGUMENT_IS_NOT_A_PARAMETER = 8145; 
    ARGS_SUPPLIED_FOR_PROCEDURE_WITHOUT_PARAMETERS = 8146; 
    STRING_OR_BINARY_TRUNCATED = 8152; 
    INVALID_POINTER = 10006; 
    WRONG_NUMBER_OF_PARAMETERS = 18751; 
    

    Başka bir şey sizin dışarı bağlantı havuzu kez SQLException alamazsanız olmasıdır - bunun yerine "Zaman aşımı doldu" bildirdiği bir InvalidOperationException olsun. Bu bir SqlException değil ama iyi değer yakalamak bir utanç.

    Bunu herhangi bir eklemeyle güncel tutmaya çalışacağım.

    1

    Geri alınabilir kodların standart listesi yok. Diğer takımlar daha önce bu problemi yaşadılar. EF ekibi bir yeniden deneme stratejisi geliştirdi. Kodlarını basmak isteyebilirsin. Ama liste tamamlanmadı. EF’in GitHub’ta listeyi değiştirdiği yerlere gittiğini gördüm.

    Bu problemi de yaşadım. SELECT * FROM sys.messages WHERE language_id = 1033 AND text LIKE '%...%''dan çıkardığım bazı bariz hata kodlarını ekledim. Ardından, onlara uygulama olarak kod ekledim.

    Ayrıca zaman aşımı ve ağ hatası için özel hata numarasını tekrar denemeniz gerekir. Bağlantı düştüğü için sunucu bu sayıyı oluşturamıyor. Bence sayı -2 idi, ama emin olmalısın.

    SQL Server'ın tanımladığı hata düzeyleri, bu amaç için (çoğunlukla da genelde) yararsızdır.

    6

    Geçici hata işleme için sql Azure'da bir sınıf [SqlDatabaseTransientErrorDetectionStrategy.cs] var. Geçici olarak düşünülebilecek neredeyse tüm özel durum kodu türlerini kapsar. Ayrıca, Retry strategy'un eksiksiz bir uygulamasıdır.

    ileride başvurmak üzere buraya pasajını ekleme: Hata numarası sql istisna iade ilave olarak eğer

    /// <summary> 
    /// Error codes reported by the DBNETLIB module. 
    /// </summary> 
    private enum ProcessNetLibErrorCode 
    { 
        ZeroBytes = -3, 
    
        Timeout = -2, 
        /* Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding. */ 
    
        Unknown = -1, 
    
        InsufficientMemory = 1, 
    
        AccessDenied = 2, 
    
        ConnectionBusy = 3, 
    
        ConnectionBroken = 4, 
    
        ConnectionLimit = 5, 
    
        ServerNotFound = 6, 
    
        NetworkNotFound = 7, 
    
        InsufficientResources = 8, 
    
        NetworkBusy = 9, 
    
        NetworkAccessDenied = 10, 
    
        GeneralError = 11, 
    
        IncorrectMode = 12, 
    
        NameNotFound = 13, 
    
        InvalidConnection = 14, 
    
        ReadWriteError = 15, 
    
        TooManyHandles = 16, 
    
        ServerError = 17, 
    
        SSLError = 18, 
    
        EncryptionError = 19, 
    
        EncryptionNotSupported = 20 
    } 
    

    bir switch case kontrol etmek:

    switch (err.Number) 
    { 
        // SQL Error Code: 40501 
        // The service is currently busy. Retry the request after 10 seconds. Code: (reason code to be decoded). 
        case ThrottlingCondition.ThrottlingErrorNumber: 
         // Decode the reason code from the error message to determine the grounds for throttling. 
         var condition = ThrottlingCondition.FromError(err); 
    
         // Attach the decoded values as additional attributes to the original SQL exception. 
         sqlException.Data[condition.ThrottlingMode.GetType().Name] = 
          condition.ThrottlingMode.ToString(); 
         sqlException.Data[condition.GetType().Name] = condition; 
    
         return true; 
    
        // SQL Error Code: 10928 
        // Resource ID: %d. The %s limit for the database is %d and has been reached. 
        case 10928: 
        // SQL Error Code: 10929 
        // Resource ID: %d. The %s minimum guarantee is %d, maximum limit is %d and the current usage for the database is %d. 
        // However, the server is currently too busy to support requests greater than %d for this database. 
        case 10929: 
        // SQL Error Code: 10053 
        // A transport-level error has occurred when receiving results from the server. 
        // An established connection was aborted by the software in your host machine. 
        case 10053: 
        // SQL Error Code: 10054 
        // A transport-level error has occurred when sending the request to the server. 
        // (provider: TCP Provider, error: 0 - An existing connection was forcibly closed by the remote host.) 
        case 10054: 
        // SQL Error Code: 10060 
        // A network-related or instance-specific error occurred while establishing a connection to SQL Server. 
        // The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server 
        // is configured to allow remote connections. (provider: TCP Provider, error: 0 - A connection attempt failed 
        // because the connected party did not properly respond after a period of time, or established connection failed 
        // because connected host has failed to respond.)"} 
        case 10060: 
        // SQL Error Code: 40197 
        // The service has encountered an error processing your request. Please try again. 
        case 40197: 
        // SQL Error Code: 40540 
        // The service has encountered an error processing your request. Please try again. 
        case 40540: 
        // SQL Error Code: 40613 
        // Database XXXX on server YYYY is not currently available. Please retry the connection later. If the problem persists, contact customer 
        // support, and provide them the session tracing ID of ZZZZZ. 
        case 40613: 
        // SQL Error Code: 40143 
        // The service has encountered an error processing your request. Please try again. 
        case 40143: 
        // SQL Error Code: 233 
        // The client was unable to establish a connection because of an error during connection initialization process before login. 
        // Possible causes include the following: the client tried to connect to an unsupported version of SQL Server; the server was too busy 
        // to accept new connections; or there was a resource limitation (insufficient memory or maximum allowed connections) on the server. 
        // (provider: TCP Provider, error: 0 - An existing connection was forcibly closed by the remote host.) 
        case 233: 
        // SQL Error Code: 64 
        // A connection was successfully established with the server, but then an error occurred during the login process. 
        // (provider: TCP Provider, error: 0 - The specified network name is no longer available.) 
        case 64: 
        // DBNETLIB Error Code: 20 
        // The instance of SQL Server you attempted to connect to does not support encryption. 
        case (int)ProcessNetLibErrorCode.EncryptionNotSupported: 
         return true; 
    } 
    

    tam source here bakınız.

    +1

    Bu güzel. Sadece bu listenin hala tamamlanmadığına dair bir not ekleyerek. EF, bu konuda başka kimseler gibi clueless. Eşyaları unutuyorlar. Örnek: Anlık görüntü yalıtımı yazışmaları. Ayrıca, bu listeden çıkmazı görmüyorum, ki bu çok şüpheli değerin listesi anlamına gelir. – usr

    +0

    Evet .. Kabul ediyorum !!Ama başlamak için iyi bir liste. – vendettamit

    +0

    Teşekkürler @vendettamit - iyi görünüyor ama usr bahseder gibi, bir çıkmazı özlüyor olsaydı, muhtemelen tekrar denemekle ilgileneceğim ana konulardan biri olduğundan biraz şüpheli hissettiriyor. Belki de EF'in otomatik olarak tekrar denemeye karar verebileceği bir şey değil midir? – thab