Créer une application Blazor Server CRUD avec EF Core et DB2 for i (IBM i)
Introduction
Ce tutoriel montre comment créer une application Blazor Server connectée à une base DB2 for i via l'extension Entity Framework Core de NTi, compatible avec .NET 8, .NET 9 et .NET 10.
L'objectif est de mettre en place un CRUD complet pour gérer des produits, catégories et commandes depuis une application web .NET moderne.
Cette approche permet d'utiliser EF Core sur IBM i pour simplifier l'accès aux données et accélérer le développement d'applications métiers.
Les commandes de ce tutoriel ciblent .NET 8 : pour .NET 9 ou .NET 10, remplacez simplement la version du framework et les versions de packages indiquées à l'étape 1. Côté serveur, le volet EF Core de NTi requiert IBM i 7.2 ou supérieur.
Étape 1 - Créer et configurer le projet
Créez le projet depuis la ligne de commande :
dotnet new blazor -n myApp -f net8.0 -int Server
cd myApp
💡 Le template
blazorservern'existe plus depuis .NET 8. Le templateblazoravec l'option-int Server(interactivité Server) crée une Blazor Web App au comportement équivalent, dont les pages se trouvent dansComponents/Pages. Pour .NET 9 ou .NET 10, remplaceznet8.0parnet9.0ounet10.0.
Ajoutez les packages nécessaires :
dotnet add package Aumerial.Data.Nti
dotnet add package Aumerial.EntityFrameworkCore --version 8.5.0
dotnet add package Microsoft.EntityFrameworkCore.Design --version 8.0.*
La version d'Aumerial.EntityFrameworkCore se choisit selon la version d'EF Core ciblée : la majeure suit EF Core, la mineure correspond à la génération NTi.
| Cible | Aumerial.EntityFrameworkCore | Packages Microsoft EF Core |
|---|---|---|
| .NET 8 (EF Core 8) | 8.5.0 |
8.0.* |
| .NET 9 (EF Core 9) | 9.5.0 |
9.0.* |
| .NET 10 (EF Core 10) | 10.5.0 |
10.0.* |
💡 Les trois versions s'appuient sur le provider ADO.NET
Aumerial.Data.Nti5.0.0, installé automatiquement comme dépendance si vous omettez la première commande.
Ajoutez la chaîne de connexion dans appsettings.json en spécifiant le schéma par défaut (la bibliothèque) dans lequel toutes les entités créées seront placées :
{
"ConnectionStrings": {
"DefaultConnection": "server=Server;user=User;password=Pwd;database=Db;pooling=true"
}
}
💡 Le pooling de connexions est inactif par défaut avec NTi 5 :
pooling=trueest recommandé pour toute application web.
Étape 2 - Définir les entités
Créez un dossier Models et ajoutez les classes suivantes :
Category.cs
Une catégorie peut contenir plusieurs produits :
public class Category
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection Products { get; set; }
}
Product.cs
Un produit appartient à une catégorie et peut être lié à plusieurs commandes :
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; }
public ICollection Orders { get; set; } = new List();
}
Order.cs
Une commande peut contenir plusieurs produits :
public class Order
{
public int Id { get; set; }
public DateTime OrderDate { get; set; }
public DateTime? DeliveryDate { get; set; }
public decimal TotalAmount { get; set; }
public ICollection Products { get; set; }
} Étape 3 - Configurer le DbContext
Ajoutez une classe AppDbContext héritant de DbContext pour gérer les entités et leurs relations :
using Microsoft.EntityFrameworkCore;
public class AppDbContext : DbContext
{
public AppDbContext(DbContextOptions options) : base(options) { }
public DbSet Products { get; set; }
public DbSet Categories { get; set; }
public DbSet Orders { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
}
} Étape 4 - Configurer Program.cs
Configurez le DbContext dans Program.cs et enregistrez-le comme service via l'injection de dépendances pour vos composants Blazor. Ajoutez using Aumerial.EntityFrameworkCore; en haut du fichier pour rendre la méthode UseNTi accessible :
using Aumerial.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext(options =>
options.UseNTi(connectionString));
💡
AddDbContextest recommandé pour la plupart des applications Blazor Server. LeDbContextest instancié avec une durée de vie Scoped, recréé à chaque requête utilisateur. UtilisezAddDbContextFactorypour les tâches en arrière-plan ou les traitements multi-threads (voir la documentation Microsoft).
Étape 5 - Créer et gérer les migrations
Générez une migration initiale pour créer les tables dans la base de données. Cette commande va créer un fichier dans le dossier Migrations contenant les instructions SQL pour créer vos tables :
dotnet ef migrations add InitialCreate
Appliquez ensuite la migration :
dotnet ef database update

Pour ajouter ou modifier une table, créez ou modifiez l'entité concernée, ajoutez-la dans AppDbContext si nécessaire, puis générez une nouvelle migration :
dotnet ef migrations add MyNewMigration
dotnet ef database update
Pour supprimer la dernière migration avant son application :
dotnet ef migrations remove
Pour revenir à une version antérieure de la base :
dotnet ef database update MigrationName
Remplacez
MigrationNamepar le nom de la migration vers laquelle vous souhaitez revenir.
Étape 6 - Ajouter un jeu de données initial
Ajoutez un jeu de données dans Program.cs, après var app = builder.Build(); :
using (var scope = app.Services.CreateScope())
{
var context = scope.ServiceProvider.GetRequiredService();
var categories = new List
{
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
{
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
{
new Order
{
OrderDate = DateTime.Now.AddDays(-10),
DeliveryDate = DateTime.Now.AddDays(-7),
TotalAmount = 750,
Products = new List { products[0], products[1], products[3] }
},
new Order
{
OrderDate = DateTime.Now.AddDays(-5),
DeliveryDate = DateTime.Now.AddDays(-3),
TotalAmount = 600,
Products = new List { products[4], products[5], products[6] }
},
new Order
{
OrderDate = DateTime.Now.AddDays(-2),
DeliveryDate = null,
TotalAmount = 290,
Products = new List { products[2], products[7] }
}
};
context.Orders.AddRange(orders);
await context.SaveChangesAsync();
}
💡
SaveChangesAsyncest la voie normale avec NTi : l'async y est réel de bout en bout, sans sync-over-async. LeSaveChangessynchrone reste disponible.
Étape 7 - Générer les pages CRUD
Visual Studio peut générer automatiquement les composants Razor CRUD pour chacune de vos entités en quelques clics.
- Clic droit sur le dossier Components/Pages de votre projet
- Sélectionnez Ajouter > Nouvel élément généré automatiquement > Composants Razor avec Entity Framework (CRUD)
- Configurez les options :
- Classe de Modèle : sélectionnez l'entité souhaitée (ex.
Product) - Classe de DbContext : sélectionnez
AppDbContext
- Classe de Modèle : sélectionnez l'entité souhaitée (ex.
Visual Studio génère automatiquement un ensemble de composants Razor CRUD dans un dossier dédié (ex. Components/Pages/ProductPages) :
Index.razor- liste des enregistrementsCreate.razor- formulaire d'ajoutEdit.razor- formulaire de modificationDetails.razor- affichage du détail d'un enregistrementDelete.razor- confirmation et suppression
Répétez l'opération pour chaque entité : Category, Order.
Étape 8 - Ajouter un champ image (BLOB)
Ajoutez un champ Image de type byte[] à l'entité Product :
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
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; }
public ICollection Orders { get; set; } = new List();
[Column(TypeName = "BLOB(1M)"), DataType(DataType.Upload)]
public byte[] Image { get; set; }
}
Générez et appliquez la migration :
dotnet ef migrations add AddProductImage
dotnet ef database update
Modifiez ensuite les composants Components/Pages/ProductPages/Create.razor et Edit.razor pour ajouter le champ d'upload :
@if (Product?.Image != null && Product.Image.Length > 0)
{
Image actuelle :
}
else
{
Aucune image disponible
}
Et la méthode pour gérer l'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();
}
}

Et maintenant ?
- Entity Framework Core - configuration, types de données et migrations
- Authentification Identity - protéger l'application avec ASP.NET Core Identity stocké dans DB2 for i
- Connexion - chaîne de connexion, pool, MFA
- Guide de démarrage rapide - première connexion et premiers appels IBM i