En este tutorial vamos a explorar el objeto DBContext, que representa el componente central de Entity Framework y actúa como puente entre nuestra aplicación .NET y la base de datos subyacente.
El DBContext es la clase principal que nos permite interactuar con la base de datos sin escribir SQL directamente, proporcionando los métodos para realizar operaciones de lectura, escritura, actualización y eliminación de datos.
Características principales
- Permite definir el modelo de datos mediante propiedades
DbSet<T>
- Se encarga de gestionar las conexiones con la base de datos
- Permite realizar consultas a la base de datos utilizando LINQ
- Ofrece métodos para gestionar el ciclo de vida de las entidades
En otras palabras, es la clase más importante y el núcleo de Entity Framework, ya que es la que nos permite interactuar con la base de datos sin necesidad de escribir SQL manualmente.
Configuración básica del DbContext
Para usar la clase DbContext
generalmente creamos una clase que hereda de ella, en la que definimos qué tablas (entidades) estarán asociadas a nuestra base de datos.
Dentro de nuestra clase DbContext
(que hereda de ella)
- Definiremos propiedades de tipo
DbSet<T>
, que representan las tablas en la base de datos. - Cada
DbSet<T>
permite interactuar con la tabla asociada, dondeT
es el tipo de la entidad (por ejemplo,User
oProduct
).
Vamos a verlo con un ejemplo,
using Microsoft.EntityFrameworkCore;
public class MiContexto : DbContext
{
// Representa la tabla "Productos" en la base de datos
public DbSet<Producto> Productos { get; set; }
// Representa la tabla "Clientes" en la base de datos
public DbSet<Cliente> Clientes { get; set; }
}
En este ejemplo,
- Hemos creado una clase llamada
MiContexto
que hereda deDbContext
- Dentro de esta clase, hemos definido dos propiedades
DbSet
:Productos
yClientes
- Estas propiedades representan las tablas de la base de datos.
Configurar la conexión a la base de datos
El DbContext
necesita saber cómo conectarse a la base de datos. Tenemos varias formas de pasarle la configuración,
En aplicaciones donde no tenemos un servicio de inyección de dependencias (típicamente aplicaciones de consola o escritorio) podemos usar el método OnConfiguring
para establecer la configuración
public class MiContexto : DbContext
{
public DbSet<Producto> Productos { get; set; }
public DbSet<Cliente> Clientes { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
const string connectionString = Configuration.GetConnectionString("DefaultConnection");
// Configura la conexión a SQL Server
optionsBuilder.UseSqlServer(connectionString);
}
}
En este ejemplo, hemos sobrescrito el método OnConfiguring
para especificar la cadena de conexión a SQL Server.
En aplicaciones ASP.NET Core, lo habitual y recomendable recomendable utilizar la inyección de dependencias para configurar el DbContext
.
Generalmente esto lo configuraremos en el fichero Program.cs
de la aplicación, usando el método AddDbContext
del contenedor de servicios,
const string connectionString = Configuration.GetConnectionString("DefaultConnection");
// Configura el DbContext para usar SQL Server
services.AddDbContext<MiContexto>(options =>
options.UseSqlServer(connectionString)
);
En algunas aplicaciónes, el alcance de inyección de dependencias no coincide con la vida útil deseada del DbContext (por ejemplo, en Blazor, donde la conexión es persistente, no por solicitud).
En este caso podemos registrar una factoria, que puede crear nuevas instancias de DbContext bajo demanda,
services.AddDbContextFactory<MiContexto>(options =>
options.UseSqlServer(connectionString);
Después, los servicios que usen la factoría podrían crear un nuevo DbContext
haciendo
MiContexto context = _contextFactory.CreateDbContext()
Uso adecuado del ciclo de vida
El DbContext
debe tener un ciclo de vida limitado. Normalmente configura como Scoped en el contenedor de DI, lo que asegura que se crea una instancia por cada solicitud HTTP
Operaciones comunes con el DbContext
Ahora que tenemos configurado nuestro DbContext
y hemos definido las clases con DbSet
ya podríamos hacer operaciones con ella.
Por ejemplo, veamos algunas de las operaciones básicas CRUD (Create Read Update y Delete)
El método Add
o AddRange
se utiliza para insertar nuevas entidades en la base de datos:
var newUser = new User { Name = "Luis Llamas", Email = "[email protected]" };
_context.Users.Add(newUser);
await _context.SaveChangesAsync();
Las consultas se realizan mediante LINQ:
var user = await _context.Users
.FirstOrDefaultAsync(u => u.Email == "[email protected]");
Modifica los datos en memoria y guarda los cambios:
var user = await _context.Users.FindAsync(1);
if (user != null)
{
user.Name = "Luis Updated";
await _context.SaveChangesAsync();
}
Elimina entidades usando Remove
:
var user = await _context.Users.FindAsync(1);
if (user != null)
{
_context.Users.Remove(user);
await _context.SaveChangesAsync();
}
¿A que es fácil? ¡Pero hay mucho más! Iremos viendo todos estos elementos en profundidad en los próximos tutoriales.