Aracılığıyla paylaş


ASP.NET Web Forms Bağlantı Dayanıklılığı ve Komut Durdurma

tarafından Erik Reitan

Bu öğreticide Wingtip Toys örnek uygulamasını bağlantı dayanıklılığını ve komut kesmeyi destekleyecek şekilde değiştireceksiniz. Bağlantı dayanıklılığını etkinleştiren Wingtip Toys örnek uygulaması, bulut ortamına özgü geçici hatalar oluştuğunda veri çağrılarını otomatik olarak yeniden dener. Ayrıca, komut kesme işlemini uygulayarak Wingtip Toys örnek uygulaması, günlüğe kaydetmek veya değiştirmek için veritabanına gönderilen tüm SQL sorgularını yakalar.

Not

Bu Web Forms öğreticisi, Tom Dykstra'nın aşağıdaki MVC öğreticisini temel aldı:
ASP.NET MVC Uygulamasında Entity Framework ile Bağlantı Dayanıklılığı ve Komut Kesme

Öğrenecekleriniz:

  • Bağlantı dayanıklılığı sağlama.
  • Komut kesme işlemini uygulama.

Önkoşullar

Başlamadan önce bilgisayarınızda aşağıdaki yazılımların yüklü olduğundan emin olun:

Bağlantı dayanıklılığı

Bir uygulamayı Windows Azure'a dağıtmayı düşündüğünüzde, göz önünde bulundurmanız gereken bir seçenek veritabanını bir bulut veritabanı hizmeti olan Windows Azure SQL Veritabanı'e dağıtmaktır. Geçici bağlantı hataları genellikle bir bulut veritabanı hizmetine bağlandığınızda, web sunucunuzla veritabanı sunucunuz aynı veri merkezinde doğrudan birbirine bağlandığından daha sık görülür. Bulut web sunucusu ve bulut veritabanı hizmeti aynı veri merkezinde barındırılıyor olsa bile, aralarında yük dengeleyiciler gibi sorunlarla karşılaşabilecek daha fazla ağ bağlantısı vardır.

Ayrıca bulut hizmeti genellikle diğer kullanıcılar tarafından paylaşılır ve bu da yanıt hızının onlardan etkilenebileceği anlamına gelir. Veritabanına erişiminiz de azaltmaya tabi olabilir. Azaltma, veritabanı hizmetinin Hizmet Düzeyi Sözleşmenizde (SLA) izin verilenden daha sık erişmeye çalıştığınızda özel durumlar oluşturacak olması anlamına gelir.

Bir bulut hizmetine erişirken oluşan bağlantı sorunlarının çoğu veya çoğu geçicidir, yani kısa bir süre içinde çözülür. Bu nedenle, bir veritabanı işlemini denediğinizde ve genellikle geçici olan bir hata türü aldığınızda, kısa bir beklemeden sonra işlemi yeniden deneyebilirsiniz ve işlem başarılı olabilir. Geçici hataları otomatik olarak yeniden deneyerek ve çoğu müşteri tarafından görünmez hale getirerek işlerseniz kullanıcılarınız için çok daha iyi bir deneyim sağlayabilirsiniz. Entity Framework 6'daki bağlantı dayanıklılığı özelliği, başarısız SQL sorgularını yeniden deneme işlemini otomatikleştirir.

Bağlantı dayanıklılığı özelliği, belirli bir veritabanı hizmeti için uygun şekilde yapılandırılmalıdır:

  1. Hangi özel durumların geçici olabileceğini bilmesi gerekir. Örneğin, program hatalarının neden olduğu hataları değil, ağ bağlantısındaki geçici bir kaybın neden olduğu hataları yeniden denemek istiyorsunuz.
  2. Başarısız bir işlemin yeniden denemeleri arasında uygun bir süre beklemesi gerekir. Bir toplu işlem için yeniden denemeler arasında, kullanıcının yanıt beklediği çevrimiçi bir web sayfasında beklemekten daha uzun süre bekleyebilirsiniz.
  3. Vazgeçmeden önce uygun sayıda yeniden denemesi gerekir. Bir toplu işlemde daha fazla kez yeniden denemek isteyebilirsiniz ve bunu çevrimiçi uygulamada yapabilirsiniz.

Bir Entity Framework sağlayıcısı tarafından Çevre desteği tüm veritabanları için bu ayarları el ile yapılandırabilirsiniz.

Bağlantı dayanıklılığını etkinleştirmek için yapmanız gereken tek şey, derlemenizde sınıfından DbConfiguration türetilen bir sınıf oluşturmak ve bu sınıfta SQL Veritabanı yürütme stratejisini ayarlamaktır. Bu, Entity Framework'te yeniden deneme ilkesi için başka bir terimdir.

Bağlantı dayanıklılığını uygulama

  1. Visual Studio'da WingtipToys örnek Web Forms uygulamasını indirin ve açın.

  2. WingtipToys uygulamasının Logic klasörüne WingtipToysConfiguration.cs adlı bir sınıf dosyası ekleyin.

  3. Mevcut kodu aşağıdaki kodla değiştirin:

    using System.Data.Entity;
    using System.Data.Entity.SqlServer;
     
    namespace WingtipToys.Logic
    {
        public class WingtipToysConfiguration : DbConfiguration
        {
            public WingtipToysConfiguration()
            {
              SetExecutionStrategy("System.Data.SqlClient", () => new SqlAzureExecutionStrategy());
            }
        }
    }
    

Entity Framework, öğesinden DbConfigurationtüretilen bir sınıfta bulduğu kodu otomatik olarak çalıştırır. Sınıfını DbConfiguration kullanarak Web.config dosyasında aksi takdirde gerçekleştirdiğiniz kodda yapılandırma görevlerini gerçekleştirebilirsiniz. Daha fazla bilgi için bkz . EntityFramework Kod Tabanlı Yapılandırma.

  1. Logic klasöründe AddProducts.cs dosyasını açın.

  2. Sarı renkle vurgulanmış olarak gösterildiği gibi için System.Data.Entity.Infrastructure bir using deyimi ekleyin:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using WingtipToys.Models;
    using System.Data.Entity.Infrastructure;
    
  3. yöntemine AddProduct bir catch blok ekleyerek öğesinin RetryLimitExceededException sarı renkle vurgulandığı şekilde günlüğe kaydedilmesini sağlamak için:

    public bool AddProduct(string ProductName, string ProductDesc, string ProductPrice, string ProductCategory, string ProductImagePath)
    {
        var myProduct = new Product();
        myProduct.ProductName = ProductName;
        myProduct.Description = ProductDesc;
        myProduct.UnitPrice = Convert.ToDouble(ProductPrice);
        myProduct.ImagePath = ProductImagePath;
        myProduct.CategoryID = Convert.ToInt32(ProductCategory);
    
        using (ProductContext _db = new ProductContext())
        {
            // Add product to DB.
            _db.Products.Add(myProduct);
            try
            {
                _db.SaveChanges();
            }
            catch (RetryLimitExceededException ex)
            {
                // Log the RetryLimitExceededException.
                WingtipToys.Logic.ExceptionUtility.LogException(ex, "Error: RetryLimitExceededException -> RemoveProductButton_Click in AdminPage.aspx.cs");
            }
        }
        // Success.
        return true;
    }
    

Özel durumu ekleyerek RetryLimitExceededException , kullanıcıya daha iyi günlük kaydı sağlayabilir veya işlemi yeniden denemeyi seçebileceği bir hata iletisi görüntüleyebilirsiniz. Özel durum yakalanarak RetryLimitExceededException geçici olma olasılığı olan tek hatalar zaten denenmiş ve birkaç kez başarısız olmuş olacaktır. Döndürülen gerçek özel durum özel durumda sarmalanır RetryLimitExceededException . Ayrıca, genel bir catch bloğu da eklediniz. Özel durum hakkında RetryLimitExceededException daha fazla bilgi için bkz . Entity Framework Bağlantı Dayanıklılığı / Yeniden Deneme Mantığı.

Komut kesme

Bir yeniden deneme ilkesini açtığınıza göre, beklendiği gibi çalıştığını doğrulamak için nasıl test edebilirsiniz? Özellikle yerel olarak çalışırken geçici bir hatanın gerçekleşmesini zorlamak o kadar kolay değildir ve gerçek geçici hataları otomatik birim testiyle tümleştirmek özellikle zor olabilir. Bağlantı dayanıklılığı özelliğini test etmek için, Entity Framework'ün SQL Server'a gönderdiği sorguları kesmenin ve SQL Server yanıtını genellikle geçici bir özel durum türüyle değiştirmenin bir yolu olmalıdır.

Bulut uygulamaları için en iyi yöntemi uygulamak için sorgu kesme özelliğini de kullanabilirsiniz: veritabanı hizmetleri gibi dış hizmetlere yapılan tüm çağrıların gecikmesini ve başarısını veya başarısızlığını günlüğe kaydetme.

Öğreticinin bu bölümünde, hem günlüğe kaydetme hem de geçici hataların benzetimini yapmak için Entity Framework'ün kesme özelliğini kullanacaksınız.

Günlük arabirimi ve sınıfı oluşturma

Günlüğe kaydetme için en iyi yöntem, sabit kodlama çağrıları System.Diagnostics.Trace veya bir günlük sınıfı yerine kullanarak interface yapmaktır. Bu, daha sonra bunu yapmanız gerekirse günlüğe kaydetme mekanizmanızı değiştirmenizi kolaylaştırır. Bu nedenle bu bölümde günlük arabirimini ve bunu uygulamak için bir sınıf oluşturacaksınız.

Yukarıdaki yordama bağlı olarak, Visual Studio'da WingtipToys örnek uygulamasını indirip açtınız.

  1. WingtipToys projesinde bir klasör oluşturun ve bunu Günlüğe Kaydetme olarak adlandırın.

  2. Günlük klasöründe ILogger.cs adlı bir sınıf dosyası oluşturun ve varsayılan kodu aşağıdaki kodla değiştirin:

    using System;
     
    namespace WingtipToys.Logging
    {
        public interface ILogger
        {
            void Information(string message);
            void Information(string fmt, params object[] vars);
            void Information(Exception exception, string fmt, params object[] vars);
    
            void Warning(string message);
            void Warning(string fmt, params object[] vars);
            void Warning(Exception exception, string fmt, params object[] vars);
    
            void Error(string message);
            void Error(string fmt, params object[] vars);
            void Error(Exception exception, string fmt, params object[] vars);
    
            void TraceApi(string componentName, string method, TimeSpan timespan);
            void TraceApi(string componentName, string method, TimeSpan timespan, string properties);
            void TraceApi(string componentName, string method, TimeSpan timespan, string fmt, params object[] vars);
    
        }
    }
    

    Arabirim, günlüklerin göreli önemini göstermek için üç izleme düzeyi ve veritabanı sorguları gibi dış hizmet çağrıları için gecikme süresi bilgileri sağlamak üzere tasarlanmış bir tane sağlar. Günlük yöntemlerinin özel durum geçirmenize olanak sağlayan aşırı yüklemeleri vardır. Bu, yığın izlemesi ve iç özel durumlar dahil olmak üzere özel durum bilgilerinin, uygulama genelindeki her günlük yöntemi çağrısında yapılmasına bağlı kalmak yerine arabirimi uygulayan sınıf tarafından güvenilir bir şekilde günlüğe kaydedilmesini sağlar.

    Yöntemler, TraceApi SQL Veritabanı gibi bir dış hizmete yapılan her çağrının gecikme süresini izlemenizi sağlar.

  3. Günlük klasöründe Logger.cs adlı bir sınıf dosyası oluşturun ve varsayılan kodu aşağıdaki kodla değiştirin:

    using System;
    using System.Diagnostics;
    using System.Text;
     
    namespace WingtipToys.Logging
    {
      public class Logger : ILogger
      {
     
        public void Information(string message)
        {
          Trace.TraceInformation(message);
        }
     
        public void Information(string fmt, params object[] vars)
        {
          Trace.TraceInformation(fmt, vars);
        }
     
        public void Information(Exception exception, string fmt, params object[] vars)
        {
          Trace.TraceInformation(FormatExceptionMessage(exception, fmt, vars));
        }
     
        public void Warning(string message)
        {
          Trace.TraceWarning(message);
        }
     
        public void Warning(string fmt, params object[] vars)
        {
          Trace.TraceWarning(fmt, vars);
        }
     
        public void Warning(Exception exception, string fmt, params object[] vars)
        {
          Trace.TraceWarning(FormatExceptionMessage(exception, fmt, vars));
        }
     
        public void Error(string message)
        {
          Trace.TraceError(message);
        }
     
        public void Error(string fmt, params object[] vars)
        {
          Trace.TraceError(fmt, vars);
        }
     
        public void Error(Exception exception, string fmt, params object[] vars)
        {
          Trace.TraceError(FormatExceptionMessage(exception, fmt, vars));
        }
     
        public void TraceApi(string componentName, string method, TimeSpan timespan)
        {
          TraceApi(componentName, method, timespan, "");
        }
     
        public void TraceApi(string componentName, string method, TimeSpan timespan, string fmt, params object[] vars)
        {
          TraceApi(componentName, method, timespan, string.Format(fmt, vars));
        }
        public void TraceApi(string componentName, string method, TimeSpan timespan, string properties)
        {
          string message = String.Concat("Component:", componentName, ";Method:", method, ";Timespan:", timespan.ToString(), ";Properties:", properties);
          Trace.TraceInformation(message);
        }
     
        private static string FormatExceptionMessage(Exception exception, string fmt, object[] vars)
        {
          var sb = new StringBuilder();
          sb.Append(string.Format(fmt, vars));
          sb.Append(" Exception: ");
          sb.Append(exception.ToString());
          return sb.ToString();
        }
      }
    }
    

Uygulama, izlemeyi yapmak için kullanır System.Diagnostics . Bu, izleme bilgilerini oluşturmayı ve kullanmayı kolaylaştıran yerleşik bir .NET özelliğidir. İzlemeyle System.Diagnostics , örneğin dosyalara günlük yazmak veya Bunları Windows Azure'da blob depolamaya yazmak için kullanabileceğiniz birçok "dinleyici" vardır. Daha fazla bilgi için Visual Studio'da Windows Azure Web Siteleri Sorunlarını Giderme bölümünde bazı seçeneklere ve diğer kaynaklara yönelik bağlantılara bakın. Bu öğreticide yalnızca Visual Studio Çıkış penceresindeki günlüklere bakacaksınız.

Bir üretim uygulamasında, dışında System.Diagnosticsizleme çerçeveleri kullanmayı düşünebilirsiniz ve ILogger arabirim, bunu yapmaya karar verirseniz farklı bir izleme mekanizmasına geçmeyi nispeten kolaylaştırır.

Kesme noktası sınıfları oluşturma

Ardından, Entity Framework'ün veritabanına her sorgu göndereceği her seferinde çağıracağı sınıfları oluşturacak, biri geçici hataların benzetimini yapacak, diğeri de günlüğe kaydetme yapacak. Bu kesme noktası sınıfları sınıfından DbCommandInterceptor türetilmelidir. Bunlarda, sorgu yürütülmek üzereyken otomatik olarak çağrılan yöntem geçersiz kılmaları yazarsınız. Bu yöntemlerde veritabanına gönderilen sorguyu inceleyebilir veya günlüğe kaydedebilir ve sorgu veritabanına gönderilmeden önce sorguyu değiştirebilir veya sorguyu veritabanına geçirmeden entity Framework'e kendiniz bir şey döndürebilirsiniz.

  1. Veritabanına gönderilmeden önce her SQL sorgusunu günlüğe kaydedecek kesme noktası sınıfını oluşturmak için Logic klasöründe InterceptorLogging.cs adlı bir sınıf dosyası oluşturun ve varsayılan kodu aşağıdaki kodla değiştirin:

    using System;
    using System.Data.Common;
    using System.Data.Entity;
    using System.Data.Entity.Infrastructure.Interception;
    using System.Data.Entity.SqlServer;
    using System.Data.SqlClient;
    using System.Diagnostics;
    using System.Reflection;
    using System.Linq;
    using WingtipToys.Logging;
    
    namespace WingtipToys.Logic
    {
      public class InterceptorLogging : DbCommandInterceptor
      {
        private ILogger _logger = new Logger();
        private readonly Stopwatch _stopwatch = new Stopwatch();
    
        public override void ScalarExecuting(DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
        {
          base.ScalarExecuting(command, interceptionContext);
          _stopwatch.Restart();
        }
    
        public override void ScalarExecuted(DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
        {
          _stopwatch.Stop();
          if (interceptionContext.Exception != null)
          {
            _logger.Error(interceptionContext.Exception, "Error executing command: {0}", command.CommandText);
          }
          else
          {
            _logger.TraceApi("SQL Database", "Interceptor.ScalarExecuted", _stopwatch.Elapsed, "Command: {0}: ", command.CommandText);
          }
          base.ScalarExecuted(command, interceptionContext);
        }
    
        public override void NonQueryExecuting(DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
        {
          base.NonQueryExecuting(command, interceptionContext);
          _stopwatch.Restart();
        }
    
        public override void NonQueryExecuted(DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
        {
          _stopwatch.Stop();
          if (interceptionContext.Exception != null)
          {
            _logger.Error(interceptionContext.Exception, "Error executing command: {0}", command.CommandText);
          }
          else
          {
            _logger.TraceApi("SQL Database", "Interceptor.NonQueryExecuted", _stopwatch.Elapsed, "Command: {0}: ", command.CommandText);
          }
          base.NonQueryExecuted(command, interceptionContext);
        }
    
        public override void ReaderExecuting(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
        {
          base.ReaderExecuting(command, interceptionContext);
          _stopwatch.Restart();
        }
        public override void ReaderExecuted(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
        {
          _stopwatch.Stop();
          if (interceptionContext.Exception != null)
          {
            _logger.Error(interceptionContext.Exception, "Error executing command: {0}", command.CommandText);
          }
          else
          {
            _logger.TraceApi("SQL Database", "Interceptor.ReaderExecuted", _stopwatch.Elapsed, "Command: {0}: ", command.CommandText);
          }
          base.ReaderExecuted(command, interceptionContext);
        }
      }
    }
    

    Başarılı sorgular veya komutlar için bu kod, gecikme süresi bilgilerini içeren bir Bilgi günlüğü yazar. Özel durumlar için bir Hata günlüğü oluşturur.

  2. AdminPage.aspx adlı sayfadaki Ad metin kutusuna "Throw" girdiğinizde işlev dışı geçici hatalar oluşturacak kesme noktası sınıfını oluşturmak için Logic klasöründe InterceptorTransientErrors.cs adlı bir sınıf dosyası oluşturun ve varsayılan kodu aşağıdaki kodla değiştirin:

    using System;
    using System.Data.Common;
    using System.Data.Entity;
    using System.Data.Entity.Infrastructure.Interception;
    using System.Data.Entity.SqlServer;
    using System.Data.SqlClient;
    using System.Diagnostics;
    using System.Reflection;
    using System.Linq;
    using WingtipToys.Logging;
     
    namespace WingtipToys.Logic
    {
      public class InterceptorTransientErrors : DbCommandInterceptor
      {
        private int _counter = 0;
        private ILogger _logger = new Logger();
     
        public override void ReaderExecuting(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
        {
          bool throwTransientErrors = false;
          if (command.Parameters.Count > 0 && command.Parameters[0].Value.ToString() == "Throw")
          {
            throwTransientErrors = true;
            command.Parameters[0].Value = "TransientErrorExample";
            command.Parameters[1].Value = "TransientErrorExample";
          }
     
          if (throwTransientErrors && _counter < 4)
          {
            _logger.Information("Returning transient error for command: {0}", command.CommandText);
            _counter++;
            interceptionContext.Exception = CreateDummySqlException();
          }
        }
     
        private SqlException CreateDummySqlException()
        {
          // The instance of SQL Server you attempted to connect to does not support encryption
          var sqlErrorNumber = 20;
     
          var sqlErrorCtor = typeof(SqlError).GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic).Where(c => c.GetParameters().Count() == 7).Single();
          var sqlError = sqlErrorCtor.Invoke(new object[] { sqlErrorNumber, (byte)0, (byte)0, "", "", "", 1 });
     
          var errorCollection = Activator.CreateInstance(typeof(SqlErrorCollection), true);
          var addMethod = typeof(SqlErrorCollection).GetMethod("Add", BindingFlags.Instance | BindingFlags.NonPublic);
          addMethod.Invoke(errorCollection, new[] { sqlError });
     
          var sqlExceptionCtor = typeof(SqlException).GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic).Where(c => c.GetParameters().Count() == 4).Single();
          var sqlException = (SqlException)sqlExceptionCtor.Invoke(new object[] { "Dummy", errorCollection, null, Guid.NewGuid() });
     
          return sqlException;
        }
      }
    }
    

    Bu kod yalnızca birden çok veri satırı döndürebilen sorgular ReaderExecuting için çağrılan yöntemini geçersiz kılar. Diğer sorgu türleri için bağlantı dayanıklılığını denetlemek istiyorsanız, günlük kesme aracının NonQueryExecuting yaptığı gibi ve ScalarExecuting yöntemlerini de geçersiz kılabilirsiniz.

    Daha sonra "Yönetici" olarak oturum açar ve üst gezinti çubuğundaki Yönetici bağlantısını seçersiniz. Ardından AdminPage.aspx sayfasında "Throw" adlı bir ürün ekleyebilirsiniz. Kod, genellikle geçici olduğu bilinen 20 numaralı hata için bir sahte SQL Veritabanı özel durumu oluşturur. Şu anda geçici olarak tanınan diğer hata numaraları 64, 233, 10053, 10054, 10060, 10928, 10929, 40197, 40501 ve 40613'tür, ancak bunlar yeni SQL Veritabanı sürümlerinde değiştirilebilir. Ürün, InterceptorTransientErrors.cs dosyasının kodunda izleyebileceğiniz "TransientErrorExample" olarak yeniden adlandırılacaktır.

    Kod, sorguyu çalıştırmak ve sonuçları geri geçirmek yerine Entity Framework'e özel durumu döndürür. Geçici özel durum dört kez döndürülür ve kod sorguyu veritabanına geçirmenin normal yordamına geri döner.

    Her şey günlüğe kaydedildiğinden, Entity Framework'ün son başarılı olmadan önce sorguyu dört kez yürütmeye çalıştığını ve uygulamadaki tek fark, sorgu sonuçları içeren bir sayfayı işlemenin daha uzun sürmesi olduğunu görebilirsiniz.

    Entity Framework'ün yeniden deneme sayısı yapılandırılabilir; kod dört kez belirtir çünkü bu, SQL Veritabanı yürütme ilkesi için varsayılan değerdir. Yürütme ilkesini değiştirirseniz, burada geçici hataların kaç kez oluşturulduğunu belirten kodu da değiştirirsiniz. Entity Framework'ün özel durumu oluşturması RetryLimitExceededException için kodu daha fazla özel durum oluşturacak şekilde de değiştirebilirsiniz.

  3. Global.asax dosyasında aşağıdaki using deyimlerini ekleyin:

    using System.Data.Entity.Infrastructure.Interception;
    
  4. Ardından, vurgulanan satırları yöntemine Application_Start ekleyin:

    void Application_Start(object sender, EventArgs e)
    {
        // Code that runs on application startup
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);
    
        // Initialize the product database.
        Database.SetInitializer(new ProductDatabaseInitializer());
    
        // Create administrator role and user.
        RoleActions roleActions = new RoleActions();
        roleActions.createAdmin();
    
        // Add Routes.
        RegisterRoutes(RouteTable.Routes);
    
        // Logging.
        DbInterception.Add(new InterceptorTransientErrors());
        DbInterception.Add(new InterceptorLogging());
      
    }
    

Entity Framework veritabanına sorgu gönderdiğinde kesme noktası kodunuzun çalıştırılmasına neden olan kod satırlarıdır. Geçici hata benzetimi ve günlüğe kaydetme için ayrı kesme noktası sınıfları oluşturduğunuz için bunları bağımsız olarak etkinleştirip devre dışı bırakabileceğinize dikkat edin.

yöntemini kullanarak kodunuzun DbInterception.Add herhangi bir yerine kesme noktası ekleyebilirsiniz; yönteminde Application_Start olması gerekmez. Yöntemine Application_Start kesme noktası eklemediyseniz bir diğer seçenek de WingtipToysConfiguration.cs adlı sınıfı güncelleştirmek veya eklemek ve yukarıdaki kodu sınıfın oluşturucusunun WingtipToysConfiguration sonuna yerleştirmek olacaktır.

Bu kodu nereye koyarsanız koyun, aynı kesme noktası için birden çok kez yürütmemeye DbInterception.Add dikkat edin; aksi taktirde ek kesme noktası örnekleri alırsınız. Örneğin, günlük kesme noktasını iki kez eklerseniz her SQL sorgusu için iki günlük görürsünüz.

Kesiciler kayıt sırasına göre yürütülür (yöntemin DbInterception.Add çağrılma sırası). Sıra, kesme kutusunda ne yaptığınıza bağlı olarak önemli olabilir. Örneğin, bir kesme noktası özelliğine CommandText aldığı SQL komutunu değiştirebilir. SQL komutunu değiştirirse, sonraki kesme noktası özgün SQL komutunu değil değiştirilmiş SQL komutunu alır.

Geçici hata benzetimi kodunu, kullanıcı arabirimine farklı bir değer girerek geçici hatalara neden olacak şekilde yazdınız. Alternatif olarak, belirli bir parametre değerini denetlemeden geçici özel durumların sırasını her zaman oluşturmak için kesme noktası kodunu yazabilirsiniz. Ardından, yalnızca geçici hatalar oluşturmak istediğinizde kesme noktasını ekleyebilirsiniz. Ancak bunu yaparsanız, veritabanı başlatma işlemi tamamlanana kadar kesme noktasını eklemeyin. Başka bir deyişle, geçici hatalar oluşturmaya başlamadan önce varlık kümelerinizin birinde sorgu gibi en az bir veritabanı işlemi yapın. Entity Framework, veritabanı başlatma sırasında birkaç sorgu yürütür ve bunlar bir işlemde yürütülemez, bu nedenle başlatma sırasındaki hatalar bağlamın tutarsız bir duruma düşmesine neden olabilir.

Günlüğe kaydetmeyi ve bağlantı dayanıklılığını test edin

  1. Visual Studio'da F5 tuşuna basarak uygulamayı hata ayıklama modunda çalıştırın ve ardından parola olarak "Pa$$word" kullanarak "Yönetici" olarak oturum açın.

  2. Üstteki gezinti çubuğundan Yönetici'yi seçin.

  3. Uygun açıklama, fiyat ve görüntü dosyasıyla "Throw" adlı yeni bir ürün girin.

  4. Ürün Ekle düğmesine basın.
    Entity Framework sorguyu birkaç kez yeniden denerken tarayıcının birkaç saniye boyunca yanıt vermediğini fark edeceksiniz. İlk yeniden deneme çok hızlı gerçekleşir, ardından her ek yeniden denemeden önce bekleme artar. Her yeniden denemeden önce daha uzun süre bekleme işlemi üstel geri alma olarak adlandırılır.

  5. Sayfa artık yüklenmeye çalışana kadar bekleyin.

  6. Projeyi durdurun ve izleme çıkışını görmek için Visual Studio Çıkış penceresine bakın. Hata Ayıkla -Windows ->>Output seçeneğini belirleyerek Çıkış penceresini bulabilirsiniz. Günlükçünüz tarafından yazılan diğer birkaç günlüğü kaydırmanız gerekebilir.

    Veritabanına gönderilen gerçek SQL sorgularını görebildiğinize dikkat edin. Entity Framework'ün başlamak için yaptığı bazı ilk sorgular ve komutlar görürsünüz ve veritabanı sürümünü ve geçiş geçmişi tablosunu denetlersiniz.
    Çıktı Penceresi
    Uygulamayı durdurup yeniden başlatmadığınız sürece bu testi yineleyemezsiniz. Uygulamanın tek bir çalıştırmasında bağlantı dayanıklılığını birden çok kez test edebilmek istiyorsanız, içindeki InterceptorTransientErrors hata sayacını sıfırlamak için kod yazabilirsiniz.

  7. Yürütme stratejisinin (yeniden deneme ilkesi) yaptığı farkı görmek için Logic klasöründeki WingtipToysConfiguration.cs dosyasındaki satırı açıklama SetExecutionStrategy satırı yapın, Yönetici sayfasını yeniden hata ayıklama modunda çalıştırın ve "Throw" adlı ürünü yeniden ekleyin.

    Bu kez hata ayıklayıcı, sorguyu ilk kez yürütmeye çalıştığında oluşturulan ilk özel durumda hemen durur.
    Hata Ayıklama - Ayrıntıları Görüntüle

  8. SetExecutionStrategy WingtipToysConfiguration.cs dosyasındaki satırın açıklamasını kaldırın.

Özet

Bu öğreticide, bağlantı dayanıklılığını ve komut kesmeyi desteklemek için bir Web Forms örnek uygulamasını nasıl değiştirebileceğinizi gördünüz.

Sonraki Adımlar

ASP.NET Web Forms'da bağlantı dayanıklılığını ve komut kesmeyi gözden geçirdikten sonra, ASP.NET 4.5'te ASP.NET Web Forms konusunu Zaman Uyumsuz Yöntemler konusunu gözden geçirin. Bu konu başlığında, Visual Studio kullanarak zaman uyumsuz bir ASP.NET Web Forms uygulaması oluşturmanın temelleri öğretilecektir.