Create a Blazor Server Application with Entity Framework Core 8
Introduction
In this tutorial, we will create a Blazor Server application that interacts with a DB2 for i database via NTi EF Core. We will implement a simple CRUD to manipulate the data. We will use an example to manage products, categories and orders:
Step 1 - Project creation and configuration
Create a new .NET project, and choose the blazor Web App project template. In the project configuration options, select Server Interactive Render Mode, and make sure you choose .NET 8.0.
Add the necessary packages:
dotnet add package Aumerial.Data.NTi
dotnet add package Aumerial.EntityFrameworkCore
dotnet add package Microsoft.EntityFrameworkCore.Design
Add the connection string to appsettings.json
, and specify the default schema in which all created entities will be placed:
{
"ConnectionStrings": {
"DefaultConnection": "server=myserver;user=myuser;password=mypassword;database=mydb"
}
}
Step 2 - Definition of Entities
Create a Models folder to organise your entities, and add the following classes to model your data.
Category.cs
A category can contain several products.
public class Category
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<Product> Products { get; set; }
}
Product.cs
A product belongs to a category and can be linked to several orders.
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
An order may contain several products.
public class Order
{
public int Id { get; set; }
public DateTime OrderDate { get; set; }
public DateTime? DeliveryDate { get; set; }
public decimal TotalAmount { get; set; }
}
Step 3 - Configuring DbContext
Add an AppDbContext
class, which inherits from DbContext
, to manage entities and their relationships.
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)
{
}
}
Step 4 - Configuration in Program.cs
To enable the application to use DbContext
, you need to configure it in Program.cs and register it as a service via dependency injection for your Blazor components.
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<AppDbContext>(options =>
options.UseNti(connectionString));
- AddDbContext is recommended for most Blazor Server applications. The
DbContext
is instantiated with a Scoped lifetime, which means that it is recreated on every user request. - AddDbContextFactory is used for scenarios where the
DbContext
needs to be created dynamically, such as background tasks or multi-threaded processing.
Step 5 - Creating and managing Migrations
Generate an initial migration to synchronise your entities with the database. This command will create a file in the Migrations folder containing the SQL instructions for creating your tables:
dotnet ef migrations add InitialCreate
Then apply the migration to update the database and create the tables:
dotnet ef database update
The same principle applies to adding a new table or modifying an existing one. Create your entities, add them to AppDbContext
and generate a new migration to take the new table into account:
dotnet ef migrations add newEntity
Update the database to include the new table:
dotnet ef database update
If you have made a mistake, you can delete the latest migration before it is applied:
dotnet ef migrations remove
If you wish to revert to an earlier version of the database, you can specify the migration name directly
dotnet ef database update <NomMigrationPrécédente>
Step 7 - Add initial data set
Add a dataset to the database after applying the migrations. Do this in program.cs
after registering the services:
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();
}
Step 8 - Generating CRUD Pages
Add CRUD pages automatically for :
Right-click on the Pages folder > Add > Razor components with EF (CRUD).
For the Products CRUD, select Product
as the template and AppDbContext
as the context.
Step 9 - Adding a field for UPLOADing an image (BLOB)
We're going to add an Image field of type byte[]
to store the image data in the database.
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; }
// New image field
[Column(TypeName = "BLOB(1M)"), DataType(DataType.Upload)]
public byte[] Image { get; set; }
}
We generate a migration to add the new field to the products
table, then update it in the database.
dotnet ef migrations add AddProductImage
dotnet ef database update
Next, we need to modify the EditProduct
and CreateProduct
components to add a field for uploading the image:
@if (Product?.Image != null && Product.Image.Length > 0)
{
Current image :
}
else
{
No images available
}
And the method for managing the upload:
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();
}
}
Visual of the CRUD obtained from the product index page: