Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
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 DbContext minden kapcsolathoz.
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);
});
});
Fontos
A Microsoft azt javasolja, hogy a legbiztonságosabb hitelesítési folyamatot használja. Ha azure SQL-hez csatlakozik, az Azure-erőforrások felügyelt identitásai az ajánlott hitelesítési módszer.
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
Kapcsolat rugalmassága és parancs elfogása ef-vel egy ASP.NET MVC-alkalmazásban
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-kapcsolatok és -tranzakciók használata
https://devblogs.microsoft.com/cesardelatorre/using-resilient-entity-framework-core-sql-connections-and-transactions-retries-with-exponential-backoff/