Aracılığıyla paylaş


Bağlantı Dayanıklılığı

Bağlan dayanıklılık başarısız veritabanı komutlarını otomatik olarak yeniden denenir. Bu özellik, hataları algılamak ve komutları yeniden denemek için gerekli mantığı kapsülleyen bir "yürütme stratejisi" sağlayarak herhangi bir veritabanıyla birlikte kullanılabilir. EF Core sağlayıcıları, kendi veritabanı hata koşullarına ve en uygun yeniden deneme ilkelerine göre uyarlanmış yürütme stratejileri sağlayabilir.

Örneğin, SQL Server sağlayıcısı SQL Server'a (SQL Azure dahil) özel olarak uyarlanmış bir yürütme stratejisi içerir. Yeniden denenebilecek özel durum türlerinin farkındadır ve en fazla yeniden deneme sayısı, yeniden denemeler arasındaki gecikme vb. için mantıklı varsayılanlara sahiptir.

Bağlamınız için seçenekler yapılandırılırken bir yürütme stratejisi belirtilir. Bu genellikle türetilmiş bağlamınızın yöntemindedir OnConfiguring :

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    optionsBuilder
        .UseSqlServer(
            @"Server=(localdb)\mssqllocaldb;Database=EFMiscellanous.ConnectionResiliency;Trusted_Connection=True;ConnectRetryCount=0",
            options => options.EnableRetryOnFailure());
}

Startup.cs veya ASP.NET Core uygulaması için:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<PicnicContext>(
        options => options.UseSqlServer(
            "<connection string>",
            providerOptions => providerOptions.EnableRetryOnFailure()));
}

Dekont

Hatada yeniden denemenin etkinleştirilmesi EF'nin sonuç kümesini dahili olarak arabelleğe almasına neden olur ve bu da büyük sonuç kümeleri döndüren sorgular için bellek gereksinimlerini önemli ölçüde artırabilir. Daha fazla ayrıntı için bkz . arabelleğe alma ve akış .

Özel yürütme stratejisi

Varsayılanlardan herhangi birini değiştirmek istiyorsanız, kendi özel yürütme stratejinizi kaydetmeye yönelik bir mekanizma vardır.

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    optionsBuilder
        .UseMyProvider(
            "<connection string>",
            options => options.ExecutionStrategy(...));
}

Yürütme stratejileri ve işlemleri

Hataları otomatik olarak yeniden deneyen bir yürütme stratejisinin, başarısız olan bir yeniden deneme bloğundaki her işlemi oynatabilmesi gerekir. Yeniden denemeler etkinleştirildiğinde, EF Core aracılığıyla gerçekleştirdiğiniz her işlem kendi yeniden denenebilir işlemi olur. Başka bir ifadeyle, geçici bir hata oluşursa her sorgu ve her çağrısı SaveChanges() bir birim olarak yeniden denenir.

Ancak kodunuz bir birim BeginTransaction() olarak ele alınması gereken kendi işlem grubunuzu tanımlıyorsanız ve işlemin içindeki her şeyin yeniden oynatılması gerekiyorsa bir hata oluşur. Yürütme stratejisini kullanırken bunu yapmaya çalışırsanız aşağıdakine benzer bir özel durum alırsınız:

InvalidOperationException: Yapılandırılmış yürütme stratejisi 'SqlServerRetryingExecutionStrategy' kullanıcı tarafından başlatılan işlemleri desteklemez. İşlemdeki tüm işlemleri yeniden denenebilir bir birim olarak yürütmek için 'DbContext.Database.CreateExecutionStrategy()' tarafından döndürülen yürütme stratejisini kullanın.

Çözüm, yürütülmesi gereken her şeyi temsil eden bir temsilciyle yürütme stratejisini el ile çağırmaktır. Geçici bir hata oluşursa yürütme stratejisi temsilciyi yeniden çağırır.


using var db = new BloggingContext();
var strategy = db.Database.CreateExecutionStrategy();

strategy.Execute(
    () =>
    {
        using var context = new BloggingContext();
        using var transaction = context.Database.BeginTransaction();

        context.Blogs.Add(new Blog { Url = "http://blogs.msdn.com/dotnet" });
        context.SaveChanges();

        context.Blogs.Add(new Blog { Url = "http://blogs.msdn.com/visualstudio" });
        context.SaveChanges();

        transaction.Commit();
    });

Bu yaklaşım ortam işlemleriyle de kullanılabilir.


using var context1 = new BloggingContext();
context1.Blogs.Add(new Blog { Url = "http://blogs.msdn.com/visualstudio" });

var strategy = context1.Database.CreateExecutionStrategy();

strategy.Execute(
    () =>
    {
        using var context2 = new BloggingContext();
        using var transaction = new TransactionScope();

        context2.Blogs.Add(new Blog { Url = "http://blogs.msdn.com/dotnet" });
        context2.SaveChanges();

        context1.SaveChanges();

        transaction.Complete();
    });

İşlem işleme hatası ve eşzamanlılık sorunu

Genel olarak, bir bağlantı hatası olduğunda geçerli işlem geri alınır. Ancak, işlem işlenirken bağlantı bırakılırsa işlemin sonuç durumu bilinmez.

Varsayılan olarak, yürütme stratejisi işlemi geri alınmış gibi yeniden dener, ancak durum böyle değilse, yeni veritabanı durumu uyumsuzsa bir özel duruma neden olur veya işlem otomatik olarak oluşturulan anahtar değerleriyle yeni bir satır eklerken belirli bir duruma bağlı değilse veri bozulmasına neden olabilir.

Bununla başa çıkmanın birkaç yolu vardır.

Seçenek 1 - Hiçbir şey yapma (neredeyse)

İşlem işleme sırasında bağlantı hatası olasılığı düşüktür, bu nedenle bu koşul gerçekten oluşursa uygulamanızın başarısız olması kabul edilebilir olabilir.

Ancak, yinelenen bir satır eklemek yerine özel durum oluşturulmasını sağlamak için depo tarafından oluşturulan anahtarları kullanmaktan kaçınmanız gerekir. İstemci tarafından oluşturulan bir GUID değeri veya istemci tarafı değer oluşturucu kullanmayı göz önünde bulundurun.

Seçenek 2 - Uygulama durumunu yeniden oluşturma

  1. Geçerli DbContextöğesini at.
  2. Yeni DbContext bir oluşturun ve uygulamanızın durumunu veritabanından geri yükleyin.
  3. Son işlemin başarıyla tamamlanmamış olabileceğini kullanıcıya bildirin.

Seçenek 3 - Durum doğrulaması ekleme

Veritabanı durumunu değiştiren işlemlerin çoğu için başarılı olup olmadığını denetleen kod eklemek mümkündür. EF bunu kolaylaştırmak için bir uzantı yöntemi sağlar - IExecutionStrategy.ExecuteInTransaction.

Bu yöntem bir işlemi başlatır ve işler ve ayrıca işlem işlemesi sırasında geçici bir hata oluştuğunda çağrılan parametredeki verifySucceeded bir işlevi kabul eder.


using var db = new BloggingContext();
var strategy = db.Database.CreateExecutionStrategy();

var blogToAdd = new Blog { Url = "http://blogs.msdn.com/dotnet" };
db.Blogs.Add(blogToAdd);

strategy.ExecuteInTransaction(
    db,
    operation: context => { context.SaveChanges(acceptAllChangesOnSuccess: false); },
    verifySucceeded: context => context.Blogs.AsNoTracking().Any(b => b.BlogId == blogToAdd.BlogId));

db.ChangeTracker.AcceptAllChanges();

Dekont

BuradaSaveChanges, başarılı olursa SaveChanges varlığın Blog durumunu olarak değiştirmemek için Unchanged olarak ayarlanmış false olarak çağrılıracceptAllChangesOnSuccess. Bu, işleme başarısız olursa ve işlem geri alınırsa aynı işlemi yeniden denemenize olanak tanır.

Seçenek 4 - İşlemi el ile izleme

Depo tarafından oluşturulan anahtarları kullanmanız veya gerçekleştirilen işlemeye bağlı olmayan işleme hatalarını işlemek için genel bir yönteme ihtiyacınız varsa, işleme başarısız olduğunda her işlemeye denetlenen bir kimlik atanabilir.

  1. İşlemlerin durumunu izlemek için kullanılan veritabanına bir tablo ekleyin.
  2. Her işlemin başında tabloya bir satır ekleyin.
  3. İşleme sırasında bağlantı başarısız olursa, veritabanında ilgili satırın olup olmadığını denetleyin.
  4. İşleme başarılı olursa, tablonun büyümesini önlemek için ilgili satırı silin.

using var db = new BloggingContext();
var strategy = db.Database.CreateExecutionStrategy();

db.Blogs.Add(new Blog { Url = "http://blogs.msdn.com/dotnet" });

var transaction = new TransactionRow { Id = Guid.NewGuid() };
db.Transactions.Add(transaction);

strategy.ExecuteInTransaction(
    db,
    operation: context => { context.SaveChanges(acceptAllChangesOnSuccess: false); },
    verifySucceeded: context => context.Transactions.AsNoTracking().Any(t => t.Id == transaction.Id));

db.ChangeTracker.AcceptAllChanges();
db.Transactions.Remove(transaction);
db.SaveChanges();

Dekont

Doğrulama için kullanılan bağlamın, işlem işleme sırasında başarısız olması durumunda bağlantının doğrulama sırasında yeniden başarısız olma olasılığı yüksek olarak tanımlanmış bir yürütme stratejisine sahip olduğundan emin olun.

Ek kaynaklar