Una aplicación de alta calidad debe ser estable, eficaz, escalable y confiable. La confiabilidad de una aplicación depende de muchos factores, pero uno de los más importantes es la resiliencia, o la capacidad de resistir fallas o fallas durante el tiempo de ejecución. En este artículo, veremos cómo podemos brindar resiliencia a las conexiones de bases de datos en ASP.NET Core usando Entity Framework Core.
EF Core tiene una característica llamada resistencia de la conexión que reintenta automáticamente los comandos fallidos de la base de datos para mantener la conectividad durante errores transitorios o inestabilidad de la red. Al encapsular la lógica para identificar fallas y reintentar comandos, esta característica nos permite diseñar planes de ejecución para diferentes situaciones de falla de la base de datos.
Para utilizar los ejemplos de código proporcionados en este artículo, debe tener Visual Studio 2022 instalado en su sistema. Si aún no tienes una copia, puedes descargue Visual Studio 2022 aquí.
Cree un proyecto de API web ASP.NET Core en Visual Studio 2022
Para crear un proyecto de API web ASP.NET Core en Visual Studio 2022, siga los pasos que se describen a continuación.
- Inicie el IDE de Visual Studio 2022.
- Haga clic en «Crear nuevo proyecto».
- En la ventana «Crear nuevo proyecto», seleccione «ASP.NET Core Web API» de la lista de plantillas que se muestran.
- Haga clic en Siguiente.
- En la ventana «Configura tu nuevo proyecto», especifica el nombre y la ubicación del nuevo proyecto. Opcionalmente, marque la casilla de verificación «Colocar solución y proyecto en el mismo directorio», según sus preferencias.
- Haga clic en Siguiente.
- En la ventana «Información adicional», seleccione «.NET 8.0 (soporte a largo plazo)» como versión del marco y asegúrese de que la casilla «Usar controladores» esté marcada. Usaremos controladores en este proyecto.
- En otra parte de la ventana «Información adicional», deje el «Tipo de autenticación» configurado en «Ninguno» (el valor predeterminado) y asegúrese de que las casillas de verificación «Habilitar soporte de API abierta», «Configurar para HTTPS» y «Habilitar Docker» permanezcan sin marcar. No utilizaremos ninguna de esas funciones aquí.
- Haga clic en Crear.
Usaremos este proyecto ASP.NET Core Web API para trabajar con los ejemplos de código en las secciones siguientes.
Crear una estrategia de ejecución en EF Core
En EF Core, una estrategia de ejecución se define como un componente que encapsula la lógica para controlar los errores de ejecución de comandos de la base de datos y reintentarlos si los errores se consideran transitorios. Una estrategia de ejecución permite a los desarrolladores asegurarse de que sus aplicaciones puedan recuperarse correctamente de errores transitorios sin necesidad de intervención humana.
Puede crear una estrategia de ejecución utilizando el método CreateExecutionStrategy como se muestra en el fragmento de código que se proporciona a continuación.
var strategy = _context.Database.CreateExecutionStrategy(); await strategy.ExecuteAsync(async () => { await using var transaction = await _context.Database.BeginTransactionAsync(); //Write your custom code here to perform CRUD operations //against the database await transaction.CommitAsync(); });
Como puede ver en el siguiente ejemplo de código, generalmente se especifica una estrategia de ejecución en el método OnConfiguring de su clase DbContext personalizada.
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder .UseSqlServer( @"Server= mssqldb;Database=Test;Trusted_Connection=True", options => options.EnableRetryOnFailure()); }
Si usa Azure SQL Database, EF Core ya proporciona la lógica de reintento y resistencia para su base de datos. Sin embargo, debe habilitar la estrategia de ejecución de EF Core para cada conexión de DbContext que realice su aplicación si desea aprovechar la resistencia de la conexión de EF Core. El siguiente fragmento de código ilustra cómo puede habilitar conexiones SQL resistentes mediante EF Core que se reintentan cada vez que se interrumpe la conexión de la base de datos.
builder.Services.AddDbContext<LibraryContext>(options => { options.UseSqlServer(builder.Configuration["IDGConnectionString"], sqlServerOptionsAction: sqlOptions => { sqlOptions.EnableRetryOnFailure( maxRetryCount: 5, maxRetryDelay: TimeSpan.FromSeconds(45)); }); });
Usar resistencia de conexión con transacciones en EF Core
Si ha habilitado los reintentos en EF Core, cada llamada al método SaveChanges se reintentará como una unidad si se produce un error en la conexión de la base de datos. Sin embargo, si ejecuta un bloque de transacción en el código de su aplicación, utilizando el método BeginTransaction, debe invocar una estrategia de ejecución explícitamente utilizando un delegado para garantizar que se ejecuten todas las operaciones dentro de la transacción. Esto se muestra en el fragmento de código que se proporciona a continuación.
var strategy = db.Database.CreateExecutionStrategy(); strategy.Execute( () => { using var context = new LibraryContext(); using var transaction = context.Database.BeginTransaction(); context.Books.Add(new Book { Id = 1, Title = "Let us C" }); context.SaveChanges(); context.Books.Add(new Book { Id = 2, Title = "Mastering C# 8.0" }); context.SaveChanges(); transaction.Commit(); });
Manejar fallas de conexión de bases de datos en ASP.NET Core
Al trabajar con conexiones de bases de datos mediante EF Core, debe controlar posibles errores de conexión detectando excepciones y reintentando las operaciones de la base de datos. Considere la siguiente clase de entidad llamada Cliente.
public class Customer { public int Id { get; set; } public string FirstName { get; set; } = string.Empty; public string LastName { get; set; } = string.Empty; public string Address { get; set; } = string.Empty; public string City { get; set; } = string.Empty; public string PostalCode { get; set; } = string.Empty; public string Country { get; set; } = string.Empty; public string Phone { get; set; } = string.Empty; }
La siguiente lista de código ilustra la clase DbConnectService que implementa la interfaz IDbConnectService y muestra cómo se pueden implementar errores de conexión y operaciones de reintento.
public class DbConnectService : IDbConnectService { private readonly CustomDbContext _dbContext; public DbConnectService(CustomDbContext dbContext) { _dbContext = dbContext; } public async Task<Customer> GetCustomer(int customerId) { try { return await _dbContext.Customers.FindAsync(customerId); } catch (SqlException ex) { //Write your custom code here to handle // connection failure and retry the operation // or implement a fallback strategy } return await Task.FromResult<Customer>(null); } }
El código fuente de la interfaz IDbConnectService se proporciona a continuación.
public interface IDbConnectService { public Task<Customer> GetCustomer(int customerId); }
Cree una clase CustomDbContext en EF Core
Como se indicó anteriormente, normalmente especificará su estrategia de ejecución en el método OnConfiguring de su clase DbContext personalizada. La siguiente lista de código ilustra la clase CustomDbContext que extiende la clase DbContext de EF Core e implementa los métodos OnConfiguring y OnModelCreating.
public class CustomContext : DbContext { public DbSet<Customer> Customers { get; set; } public CustomContext(DbContextOptions options) : base(options) { } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder .UseSqlServer( @"Server= mssqldb;Database=Test;Trusted_Connection=True", options => options.EnableRetryOnFailure()); } protected override void OnModelCreating(ModelBuilder modelBuilder) { //Write your custom code here to //configure the models used in your application } }
Una excelente manera de manejar fallas de conexión a la base de datos y hacer que su aplicación sea resistente es usar polly, una biblioteca de manejo de fallas para .NET. Puede utilizar Polly para implementar la funcionalidad de disyuntor para que cualquier falla de conexión a la base de datos en la aplicación se maneje correctamente. Hablaré sobre el uso de Polly para implementar disyuntores en una publicación futura aquí.
Copyright © 2024 IDG Communications, Inc.