Configuración y Operaciones CRUD con Entity Framework Core 6 en Web API

  1. Creación del proyecto e instalación de dependencias

Para comenzar, generamos un nuevo proyecto de ASP.NET Core Web API utilizando Visual Studio 2022 o la CLI de .NET. Una vez creado, es necesario incorporar los paquetes NuGet requeridos para la integración con SQL Server y las herramientas de migración:

dotnet add package Microsoft.EntityFrameworkCore.SqlServer
dotnet add package Microsoft.EntityFrameworkCore.Tools
  1. Definición del modelo de dominio

Crear una clase que represente la entidad principal con la que interactuaremos en la base de datos. En este caso, modelaremos el perfil de un usuario:

public class PerfilUsuario
{
    public int Identificador { get; set; }
    public string NombreCompleto { get; set; }
    public string CorreoElectronico { get; set; }
    public string ClaveAcceso { get; set; }
    public string Alias { get; set; }
}
  1. Implementación del contexto de base de datos

El siguiente paso es definir la clase de contexto, la cual debe heredar de DbContext. Esta clase gestionará las sesiones con la base de datos y expondrá las entidades como conjuntos de datos:

public class BaseDatosContext : DbContext
{
    public BaseDatosContext(DbContextOptions<BaseDatosContext> opciones) : base(opciones) 
    { 
    }
    
    public DbSet<PerfilUsuario> Perfiles { get; set; }
}
  1. Configuración de la cadena de conexión

Las credenciales y la dirección del servidor deben almacenarse de forma segura en el archivo appsettings.json:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "ConnectionStrings": {
    "ConexionSql": "Server=localhost;Database=MiBaseDeDatosEF;User Id=sa;Password=miPasswordSeguro123!;TrustServerCertificate=True;"
  }
}
  1. Registro de servicios en el contenedor de dependencias

En el archivo Program.cs, registramos el contexto para que esté disponible mediante inyección de dependencias. Se muestran dos enfoques: el registro estándar y el patrón de fábrica, útil para escenarios con múltiples hilos o servicios de larga duración:

// Registro estándar (Scoping por solicitud HTTP)
builder.Services.AddDbContext<BaseDatosContext>(opciones =>
    opciones.UseSqlServer(builder.Configuration.GetConnectionString("ConexionSql")));

// Registro mediante fábrica
builder.Services.AddDbContextFactory<BaseDatosContext>(opciones =>
    opciones.UseSqlServer(builder.Configuration.GetConnectionString("ConexionSql")));
  1. Generación y aplicación de migraciones

Para traducir nuestro modelo de código a un esquema de base de datos real, utilizamos el sistema de migraciones. A través de la terminal o la consola del administrador de paqueets, ejecutamos los siguientes comandos:

# Crear la migración inicial
dotnet ef migrations add MigracionInicial

# Aplicar los cambios a la base de datos
dotnet ef database update

Otros comandos útiles para la gestión del esquema incluyen dotnet ef migrations remove para deshacer la última migración no aplicada, o dotnet ef dbcontext scaffold para generar entidades a partir de una base de datos existente (enfoque Database-First).

  1. Implementación del controlador para operaciones CRUD

Finalmente, creamos un controlador de API para exponer los endpoints. Aquí inyectamos tanto el contexto estándar como la fábrica, aplicando operaciones asíncronas para mejorar el rendimiento de la API:

[ApiController]
[Route("api/[controller]")]
public class PerfilesController : ControllerBase
{
    private readonly BaseDatosContext _contexto;
    private readonly IDbContextFactory<BaseDatosContext> _fabricaContexto;

    public PerfilesController(BaseDatosContext contexto, IDbContextFactory<BaseDatosContext> fabricaContexto)
    {
        _contexto = contexto;
        _fabricaContexto = fabricaContexto;
    }

    [HttpPost("crear")]
    public async Task<IActionResult> CrearPerfil()
    {
        var nuevoPerfil = new PerfilUsuario
        {
            NombreCompleto = "Juan Pérez",
            CorreoElectronico = "juan.perez@dominio.com",
            ClaveAcceso = "HashSeguro123",
            Alias = "JuanP"
        };
        
        _contexto.Perfiles.Add(nuevoPerfil);
        await _contexto.SaveChangesAsync();
        
        return Ok(nuevoPerfil);
    }

    [HttpGet("obtener/{id}")]
    public async Task<IActionResult> ObtenerPerfiles(int id)
    {
        var resultados = new List<PerfilUsuario>();
        
        var perfilDirecto = await _contexto.Perfiles.FindAsync(id);
        if (perfilDirecto != null) resultados.Add(perfilDirecto);

        using (var contextoInstancia = await _fabricaContexto.CreateDbContextAsync())
        {
            var perfilFabrica = await contextoInstancia.Perfiles.FirstOrDefaultAsync(p => p.Identificador == id);
            if (perfilFabrica != null && !resultados.Any(r => r.Identificador == perfilFabrica.Identificador))
            {
                resultados.Add(perfilFabrica);
            }
        }

        return Ok(resultados);
    }

    [HttpPut("actualizar/{id}")]
    public async Task<IActionResult> ActualizarAlias(int id, string nuevoAlias)
    {
        var perfil = await _contexto.Perfiles.FindAsync(id);
        if (perfil == null) return NotFound();

        perfil.Alias = nuevoAlias;
        await _contexto.SaveChangesAsync();
        
        return Ok(perfil);
    }

    [HttpDelete("eliminar/{id}")]
    public async Task<IActionResult> EliminarPerfil(int id)
    {
        var perfil = await _contexto.Perfiles.FindAsync(id);
        if (perfil == null) return NotFound();

        _contexto.Perfiles.Remove(perfil);
        await _contexto.SaveChangesAsync();
        
        return Ok(perfil);
    }
}

Etiquetas: Entity Framework Core ASP.NET Core Web API SQL Server C#

Publicado el 9-12 15:24