odolnost Připojení a logika opakování

Poznámka

Pouze EF6 a novější – Funkce, rozhraní API atd. popsané na této stránce byly představeny v Entity Framework 6. Pokud používáte starší verzi, některé nebo všechny informace nemusí být platné.

Aplikace připojující se k databázovému serveru byly vždy ohroženy přerušením připojení kvůli selháním back-endu a nestabilitě sítě. V prostředí založeném na síti LAN, které pracuje na vyhrazených databázových serverech, jsou však tyto chyby vzácné, že není často nutná dodatečná logika pro zpracování těchto selhání. S nárůstem cloudových databázových serverů, jako je Windows Azure SQL Database a připojení v méně spolehlivých sítích, je teď častější, když dojde k přerušení připojení. Důvodem můžou být obranné techniky, které cloudové databáze používají k zajištění nestrannosti služeb, jako je omezování připojení nebo nestabilita v síti, což způsobuje přerušované časové limity a další přechodné chyby.

Připojení odolnost proti chybám připojení označuje schopnost EF automaticky opakovat všechny příkazy, které selžou kvůli těmto přerušením připojení.

Strategie provádění

Připojení opakování se postará implementace rozhraní IDbExecutionStrategy. Implementace IDbExecutionStrategy zodpovídají za přijetí operace, a pokud dojde k výjimce, určí, jestli je opakování vhodné, a zkusíte to znovu. Existují čtyři strategie provádění, které se dodávají s EF:

  1. DefaultExecutionStrategy: Tato strategie provádění neopakuje žádné operace, jedná se o výchozí hodnotu pro databáze jiné než sql server.
  2. DefaultSqlExecutionStrategy: toto je interní strategie provádění, která se používá ve výchozím nastavení. Tato strategie se vůbec neopakuje, ale zabalí všechny výjimky, které by mohly být přechodné, aby informovaly uživatele, že by mohli chtít povolit odolnost připojení.
  3. DbExecutionStrategy: tato třída je vhodná jako základní třída pro jiné strategie provádění, včetně vlastních. Implementuje zásadu exponenciálního opakování, kdy k počátečnímu opakování dochází s nulovým zpožděním a zpoždění se exponenciálně zvýší, dokud nedojde k dosažení maximálního počtu opakování. Tato třída má abstraktní Metodu ShouldRetryOn, která lze implementovat v odvozených strategiích provádění k řízení, které výjimky by se měly opakovat.
  4. SqlAzureExecutionStrategy: Tato strategie spouštění dědí z DbExecutionStrategy a bude opakovat výjimky, o kterých je známo, že při práci s Azure SQL Database může být přechodná.

Poznámka

Strategie provádění 2 a 4 jsou součástí poskytovatele SQL Serveru, který se dodává s EF, který je v sestavení EntityFramework.SqlServer a je navržený pro práci s SQL Serverem.

Povolení strategie provádění

Nejjednodušší způsob, jak informovat EF, aby používal strategii spouštění, je metoda SetExecutionStrategy třídy DbConfiguration :

public class MyConfiguration : DbConfiguration
{
    public MyConfiguration()
    {
        SetExecutionStrategy("System.Data.SqlClient", () => new SqlAzureExecutionStrategy());
    }
}

Tento kód říká EF, aby při připojování k SQL Serveru používal SqlAzureExecutionStrategy.

Konfigurace strategie provádění

Konstruktor SqlAzureExecutionStrategy může přijmout dva parametry, MaxRetryCount a MaxDelay. MaxRetry count je maximální počet opakování strategie. MaxDelay je TimeSpan představující maximální zpoždění mezi opakovanými pokusy, které bude strategie provádění používat.

Pokud chcete nastavit maximální počet opakování na 1 a maximální prodlevu na 30 sekund, provedete následující:

public class MyConfiguration : DbConfiguration
{
    public MyConfiguration()
    {
        SetExecutionStrategy(
            "System.Data.SqlClient",
            () => new SqlAzureExecutionStrategy(1, TimeSpan.FromSeconds(30)));
    }
}

SqlAzureExecutionStrategy se bude opakovat okamžitě při prvním výskytu přechodného selhání, ale mezi jednotlivými opakováními se zpoždí delší dobu, dokud nedojde k překročení limitu maximálního počtu opakování, nebo celkový čas dosáhne maximálního zpoždění.

Strategie provádění budou opakovat pouze omezený počet výjimek, které jsou obvykle přechodné, budete stále muset zpracovat další chyby a zachytit výjimku RetryLimitExceed pro případ, kdy chyba není přechodná nebo trvá příliš dlouho, než se sama vyřeší.

Při použití strategie opakovaného spuštění existují některá známá omezení:

Dotazy streamování se nepodporují.

Ve výchozím nastavení ef6 a novější verze uloží výsledky dotazů do vyrovnávací paměti místo jejich streamování. Pokud chcete, aby se výsledky streamovaly, můžete pomocí metody AsStreaming změnit dotaz LINQ na Entity na streamování.

using (var db = new BloggingContext())
{
    var query = (from b in db.Blogs
                orderby b.Url
                select b).AsStreaming();
    }
}

Streamování není podporováno při registraci strategie opakovaného spuštění. Toto omezení existuje, protože připojení by mohlo projít vrácené výsledky. Když k tomu dojde, EF potřebuje znovu spustit celý dotaz, ale nemá žádný spolehlivý způsob, jak zjistit, které výsledky už byly vráceny (data se od odeslání počátečního dotazu můžou změnit, výsledky se můžou vrátit v jiném pořadí, výsledky nemusí mít jedinečný identifikátor atd.).

Transakce iniciované uživatelem se nepodporují.

Pokud jste nakonfigurovali strategii provádění, která vede k opakovaným pokusům, existují určitá omezení týkající se použití transakcí.

Ef ve výchozím nastavení provede všechny aktualizace databáze v rámci transakce. Pokud to chcete povolit, nemusíte nic dělat, EF to dělá vždycky automaticky.

Například v následujícím kódu SaveChanges se automaticky provádí v rámci transakce. Pokud by funkce SaveChanges po vložení některého z nových webů selhala, transakce by byla vrácena zpět a nebyly použity žádné změny v databázi. Kontext je také ponechán ve stavu, který umožňuje, aby se funkce SaveChanges znovu volala, aby se zkusily změny znovu použít.

using (var db = new BloggingContext())
{
    db.Blogs.Add(new Site { Url = "http://msdn.com/data/ef" });
    db.Blogs.Add(new Site { Url = "http://blogs.msdn.com/adonet" });
    db.SaveChanges();
}

Pokud nepoužíváte strategii opakování provádění, můžete zabalit více operací do jedné transakce. Například následující kód zabalí dvě volání SaveChanges do jedné transakce. Pokud některá část některé z operací selže, žádná z těchto změn se nepoužije.

using (var db = new BloggingContext())
{
    using (var trn = db.Database.BeginTransaction())
    {
        db.Blogs.Add(new Site { Url = "http://msdn.com/data/ef" });
        db.Blogs.Add(new Site { Url = "http://blogs.msdn.com/adonet" });
        db.SaveChanges();

        db.Blogs.Add(new Site { Url = "http://twitter.com/efmagicunicorns" });
        db.SaveChanges();

        trn.Commit();
    }
}

To není podporováno při použití strategie opakování spuštění, protože EF neví o žádných předchozích operacích a o tom, jak je opakovat. Pokud například druhý SaveChanges selhal, ef už nemá požadované informace pro opakování prvního volání SaveChanges.

Řešení: Strategie ručního provádění volání

Řešením je ručně použít strategii spouštění a poskytnout jí celou sadu logiky, která se má spustit, aby mohla opakovat všechno, pokud jedna z operací selže. Pokud je spuštěna strategie provádění odvozená z DbExecutionStrategy, pozastaví implicitní strategii spouštění použitou v SaveChanges.

Mějte na paměti, že všechny kontexty by se měly vytvořit v rámci bloku kódu, který se má opakovat. Tím se zajistí, že pro každé opakování začneme čistým stavem.

var executionStrategy = new SqlAzureExecutionStrategy();

executionStrategy.Execute(
    () =>
    {
        using (var db = new BloggingContext())
        {
            using (var trn = db.Database.BeginTransaction())
            {
                db.Blogs.Add(new Blog { Url = "http://msdn.com/data/ef" });
                db.Blogs.Add(new Blog { Url = "http://blogs.msdn.com/adonet" });
                db.SaveChanges();

                db.Blogs.Add(new Blog { Url = "http://twitter.com/efmagicunicorns" });
                db.SaveChanges();

                trn.Commit();
            }
        }
    });