En este tutorial, crearemos una aplicación Blazor Server que interactúa con una base de datos DB2 for i mediante NTi EF Core. Implementaremos un CRUD simple para manipular los datos.
Usaremos un ejemplo de gestión de productos, categorías y pedidos:
Paso 1 - Creación y Configuración del Proyecto
Cree un nuevo proyecto .NET y elija la plantilla de proyecto blazor Web App. En las opciones de configuración del proyecto, seleccione el modo de renderizado interactivo Server y asegúrese de elegir .NET 8.0.
Agregue los paquetes necesarios:
dotnet add package Aumerial.Data.NTi
dotnet add package Aumerial.EntityFrameworkCore
dotnet add package Microsoft.EntityFrameworkCore.Design
Agregue la cadena de conexión en appsettings.json
y especifique el esquema predeterminado en el que se colocarán todas las entidades creadas:
{
"ConnectionStrings": {
"DefaultConnection": "server=myserver;user=myuser;password=mypassword;database=mydb"
}
}
Paso 2 - Definición de las Entidades
Cree una carpeta Models para organizar sus entidades y agregue las siguientes clases para modelar sus datos.
Category.cs
Una categoría puede contener varios productos.
public class Category
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<Product> Products { get; set; }
}
Product.cs
Un producto pertenece a una categoría y puede estar relacionado con varios pedidos.
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public string description { get; set; }
public decimal Price { get; set; }
public int stockQuantity { get; set; }
public decimal Weight { get; set; }
public bool IsAvailable { get; set; }
public int CategoryId { get; set; }
public Category Category { get; set; }
}
Order.cs
Un pedido puede contener varios productos.
public class Order
{
public int Id { get; set; }
public DateTime OrderDate { get; set; }
public DateTime? DeliveryDate { get; set; }
public decimal TotalAmount { get; set; }
}
Paso 3 - Configuración de DbContext
Agregue una clase AppDbContext
que herede de DbContext
, para gestionar las entidades y sus relaciones.
using Microsoft.EntityFrameworkCore;
public class AppDbContext : DbContext
{
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { }
public DbSet<Product> Products { get; set; }
public DbSet<Category> Categories { get; set; }
public DbSet<Order> Orders { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
}
}
Paso 4 - Configuración en Program.cs
Para permitir que la aplicación use DbContext
, debe configurarlo en Program.cs
y registrarlo como servicio mediante inyección de dependencias para sus componentes Blazor.
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<AppDbContext>(options =>
options.UseNti(connectionString));
- AddDbContext es recomendado para la mayoría de las aplicaciones Blazor Server. El
DbContext
se instancia con un tiempo de vida Scoped, lo que significa que se recrea en cada solicitud del usuario. - AddDbContextFactory se utiliza en escenarios donde el
DbContext
debe crearse dinámicamente, como en tareas en segundo plano o procesos multi-hilo.
Paso 5 - Creación y gestión de Migraciones
Genere una migración inicial para sincronizar sus entidades con la base de datos. Este comando creará un archivo en la carpeta Migrations que contiene las instrucciones SQL para crear sus tablas:
dotnet ef migrations add InitialCreate
Luego aplique la migración para actualizar la base de datos y crear las tablas:
dotnet ef database update
Para agregar una nueva tabla o modificar una tabla existente, es el mismo principio. Cree sus entidades, agréguelas en AppDbContext
y genere una nueva migración para incluir la nueva tabla:
dotnet ef migrations add newEntity
Actualice la base de datos para incluir la nueva tabla:
dotnet ef database update
Si cometió un error, puede eliminar la última migración antes de aplicarla:
dotnet ef migrations remove
Si desea volver a una versión anterior de la base de datos, puede especificar directamente el nombre de la migración.
dotnet ef database update <NomMigrationPrécédente>
Paso 6 - Agregar conjunto de datos inicial
Agregue un conjunto de datos en la base después de aplicar las migraciones. Hágalo en program.cs
después del registro de los servicios:
using (var scope = app.Services.CreateScope())
{
var context = scope.ServiceProvider.GetRequiredService<AppDbContext>();
var categories = new List<Category>
{
new Category { Name = "Electronics" },
new Category { Name = "Books" },
new Category { Name = "Home Appliances" },
new Category { Name = "Fashion" },
new Category { Name = "Toys" }
};
context.Categories.AddRange(categories);
var products = new List<Product>
{
new Product { Name = "Smartphone", Price = 500, stockQuantity = 10, Category = categories[0], IsAvailable = true },
new Product { Name = "Laptop", Price = 1200, stockQuantity = 5, Category = categories[0], IsAvailable = true },
new Product { Name = "Washing Machine", Price = 300, stockQuantity = 8, Category = categories[2], IsAvailable = true },
new Product { Name = "T-Shirt", Price = 20, stockQuantity = 50, Category = categories[3], IsAvailable = true },
new Product { Name = "Children's Book", Price = 15, stockQuantity = 100, Category = categories[1], IsAvailable = true },
new Product { Name = "Toy Car", Price = 30, stockQuantity = 20, Category = categories[4], IsAvailable = true },
new Product { Name = "Microwave Oven", Price = 250, stockQuantity = 6, Category = categories[2], IsAvailable = true },
new Product { Name = "Jeans", Price = 40, stockQuantity = 30, Category = categories[3], IsAvailable = true }
};
context.Products.AddRange(products);
var orders = new List<Order>
{
new Order { OrderDate = DateTime.Now.AddDays(-10), DeliveryDate = DateTime.Now.AddDays(-7), TotalAmount = 750 },
new Order { OrderDate = DateTime.Now.AddDays(-5), DeliveryDate = DateTime.Now.AddDays(-3), TotalAmount = 600 },
new Order { OrderDate = DateTime.Now.AddDays(-2), DeliveryDate = null, TotalAmount = 290 }
};
context.Orders.AddRange(orders);
var orderProducts = new List<OrderProduct>
{
new OrderProduct { Order = orders[0], Product = products[0] },
new OrderProduct { Order = orders[0], Product = products[1] },
new OrderProduct { Order = orders[0], Product = products[3] },
new OrderProduct { Order = orders[1], Product = products[4] },
new OrderProduct { Order = orders[1], Product = products[5] },
new OrderProduct { Order = orders[1], Product = products[6] },
new OrderProduct { Order = orders[2], Product = products[2] },
new OrderProduct { Order = orders[2], Product = products[7] }
};
context.OrderProducts.AddRange(orderProducts);
context.SaveChanges();
}
Paso 7 - Generación de las Páginas CRUD
Agregue automáticamente las páginas CRUD para las entidades:
Clic derecho en la carpeta Pages > Agregar > Componentes Razor con EF (CRUD).
Para el CRUD de Productos, seleccione Product
como modelo y AppDbContext
como contexto.
Paso 8 - Agregar un campo para la CARGA de una imagen (BLOB)
Agregaremos un campo Image de tipo byte[]
para almacenar los datos de la imagen en la base de datos.
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public decimal Price { get; set; }
public int StockQuantity { get; set; }
public decimal Weight { get; set; }
public bool IsAvailable { get; set; }
public int CategoryId { get; set; }
public Category Category { get; set; }
// Nuevo campo para la imagen
[Column(TypeName = "BLOB(1M)"), DataType(DataType.Upload)]
public byte[] Image { get; set; }
}
Generamos una migración para agregar el nuevo campo a la tabla products
, luego actualizamos la base de datos.
dotnet ef migrations add AddProductImage
dotnet ef database update
Luego, debe modificar los componentes EditProduct
y CreateProduct
para agregar un campo que permita subir la imagen:
<div class="mb-3">
<label for="image" class="form-label">Image:</label>
<InputFile id="image" OnChange="UploadFile" class="form-control" />
@if (Product?.Image != null && Product.Image.Length > 0)
{
<p>Imagen actual :</p>
<img src="data:image/jpeg;base64,@Convert.ToBase64String(Product.Image)"
style="max-width: 200px; max-height: 200px;" />
}
else
{
<p>Ninguna imagen disponible</p>
}
</div>
Y el método para gestionar la carga:
private async Task UploadFile(InputFileChangeEventArgs e)
{
var file = e.File;
if (file != null)
{
using var memoryStream = new MemoryStream();
await file.OpenReadStream().CopyToAsync(memoryStream);
Product.Image = memoryStream.ToArray();
}
}
Vista del CRUD obtenido en la página de índice de productos:
Quentin Destrade