Rugalmas Entity Framework Core SQL-kapcsolatok implementálása
Tipp.
Ez a tartalom egy részlet a .NET-alkalmazásokhoz készült .NET-alkalmazásokhoz készült eBook, .NET Microservices Architecture című eBookból, amely elérhető a .NET Docs-on vagy egy ingyenesen letölthető PDF-fájlként, amely offline módban is olvasható.
Az Azure SQL DB esetében az Entity Framework (EF) Core már belső adatbázis-kapcsolati rugalmasságot és újrapróbálkozási logikát biztosít. Ha azonban rugalmas EF Core-kapcsolatokat szeretne használni, engedélyeznie kell az Entity Framework végrehajtási stratégiáját minden kapcsolathozDbContext.
Az EF Core-kapcsolat szintjén például az alábbi kód lehetővé teszi az olyan rugalmas SQL-kapcsolatokat, amelyek újrapróbálkozódnak, ha a kapcsolat meghiúsul.
// Program.cs from any ASP.NET Core Web API
// Other code ...
builder.Services.AddDbContext<CatalogContext>(options =>
{
options.UseSqlServer(builder.Configuration["ConnectionString"],
sqlServerOptionsAction: sqlOptions =>
{
sqlOptions.EnableRetryOnFailure(
maxRetryCount: 10,
maxRetryDelay: TimeSpan.FromSeconds(30),
errorNumbersToAdd: null);
});
});
Végrehajtási stratégiák és explicit tranzakciók a BeginTransaction és több DbContext használatával
Ha az újrapróbálkozások engedélyezve vannak az EF Core-kapcsolatokban, az EF Core használatával végrehajtott minden művelet saját újrapróbálkozási művelet lesz. Ha átmeneti hiba történik, az egyes lekérdezéseket és hívásokat SaveChanges
egységként újrapróbáljuk.
Ha azonban a kód egy tranzakciót kezdeményez, BeginTransaction
ön határozza meg a saját műveletcsoportját, amelyet egységként kell kezelni. Ha hiba történik, a tranzakció minden elemét vissza kell állítani.
Ha ef végrehajtási stratégia (újrapróbálkozási szabályzat) használatakor próbálja végrehajtani a tranzakciót, és több DbContextsből hív SaveChanges
meg, az alábbihoz hasonló kivételt fog kapni:
System.InvalidOperationException: Az SqlServerRetryingExecutionStrategy konfigurált végrehajtási stratégia nem támogatja a felhasználó által kezdeményezett tranzakciókat. Használja a DbContext.Database.CreateExecutionStrategy()) által visszaadott végrehajtási stratégiát a tranzakció összes műveletének újrapróbálkozható egységként való végrehajtásához.
A megoldás az EF végrehajtási stratégiájának manuális meghívása egy meghatalmazottal, amely minden végrehajtandó elemet képvisel. Átmeneti hiba előfordulásakor a végrehajtási stratégia ismét meghívja a delegáltat. Az alábbi kód például bemutatja, hogyan implementálható két több DbContexts (_catalogContext és IntegrationEventLogContext) eShopOnContainersben egy termék frissítésekor, majd a ProductPriceChangedIntegrationEvent objektum mentésekor, amelynek egy másik DbContextet kell használnia.
public async Task<IActionResult> UpdateProduct(
[FromBody]CatalogItem productToUpdate)
{
// Other code ...
var oldPrice = catalogItem.Price;
var raiseProductPriceChangedEvent = oldPrice != productToUpdate.Price;
// Update current product
catalogItem = productToUpdate;
// Save product's data and publish integration event through the Event Bus
// if price has changed
if (raiseProductPriceChangedEvent)
{
//Create Integration Event to be published through the Event Bus
var priceChangedEvent = new ProductPriceChangedIntegrationEvent(
catalogItem.Id, productToUpdate.Price, oldPrice);
// Achieving atomicity between original Catalog database operation and the
// IntegrationEventLog thanks to a local transaction
await _catalogIntegrationEventService.SaveEventAndCatalogContextChangesAsync(
priceChangedEvent);
// Publish through the Event Bus and mark the saved event as published
await _catalogIntegrationEventService.PublishThroughEventBusAsync(
priceChangedEvent);
}
// Just save the updated product because the Product's Price hasn't changed.
else
{
await _catalogContext.SaveChangesAsync();
}
}
Az első DbContext , _catalogContext
a második DbContext
pedig az objektumon _catalogIntegrationEventService
belül van. A véglegesítési műveletet az összes DbContext
objektumon végrehajtja egy EF végrehajtási stratégia használatával.
A több DbContext
véglegesítés eléréséhez a SaveEventAndCatalogContextChangesAsync
rendszer egy osztályt ResilientTransaction
használ, ahogyan az a következő kódban látható:
public class CatalogIntegrationEventService : ICatalogIntegrationEventService
{
//…
public async Task SaveEventAndCatalogContextChangesAsync(
IntegrationEvent evt)
{
// Use of an EF Core resiliency strategy when using multiple DbContexts
// within an explicit BeginTransaction():
// https://learn.microsoft.com/ef/core/miscellaneous/connection-resiliency
await ResilientTransaction.New(_catalogContext).ExecuteAsync(async () =>
{
// Achieving atomicity between original catalog database
// operation and the IntegrationEventLog thanks to a local transaction
await _catalogContext.SaveChangesAsync();
await _eventLogService.SaveEventAsync(evt,
_catalogContext.Database.CurrentTransaction.GetDbTransaction());
});
}
}
A ResilientTransaction.ExecuteAsync
metódus alapvetően elindít egy tranzakciót az átadott DbContext
(_catalogContext
) értékről, majd ezt a EventLogService
tranzakciót használja a módosítások mentéséhez, IntegrationEventLogContext
majd véglegesíti a teljes tranzakciót.
public class ResilientTransaction
{
private DbContext _context;
private ResilientTransaction(DbContext context) =>
_context = context ?? throw new ArgumentNullException(nameof(context));
public static ResilientTransaction New (DbContext context) =>
new ResilientTransaction(context);
public async Task ExecuteAsync(Func<Task> action)
{
// Use of an EF Core resiliency strategy when using multiple DbContexts
// within an explicit BeginTransaction():
// https://learn.microsoft.com/ef/core/miscellaneous/connection-resiliency
var strategy = _context.Database.CreateExecutionStrategy();
await strategy.ExecuteAsync(async () =>
{
await using var transaction = await _context.Database.BeginTransactionAsync();
await action();
await transaction.CommitAsync();
});
}
}
További erőforrások
Csatlakozás ion Resiliency and Command Interception with EF in a ASP.NET MVC Application
https://learn.microsoft.com/aspnet/mvc/overview/getting-started/getting-started-with-ef-using-mvc/connection-resiliency-and-command-interception-with-the-entity-framework-in-an-asp-net-mvc-applicationCesar de la Torre. Rugalmas Entity Framework Core SQL-Csatlakozás ions és tranzakciók használata
https://devblogs.microsoft.com/cesardelatorre/using-resilient-entity-framework-core-sql-connections-and-transactions-retries-with-exponential-backoff/
Visszajelzés
https://aka.ms/ContentUserFeedback.
Hamarosan elérhető: 2024-ben fokozatosan kivezetjük a GitHub-problémákat a tartalom visszajelzési mechanizmusaként, és lecseréljük egy új visszajelzési rendszerre. További információ:Visszajelzés küldése és megtekintése a következőhöz: