Contextes EF Core Lagoon
Lagoon fournit des classes de base EF Core qui intègrent ASP.NET Identity, les entités internes du framework et les conventions applicatives. Le contexte applicatif est généralement nommé ApplicationDbContext et se place dans le projet Model.
Choisir la classe de base
Le choix se fait d'abord sur le type de clé Identity, puis sur le besoin de suivi des modifications.
| Classe de base | Type de clé utilisateur/rôle | Suivi des modifications | Contrainte utilisateur |
|---|---|---|---|
LgApplicationDbContext<TUser> | string | Non | TUser hérite de LgIdentityUser |
LgApplicationDbContextGuid<TUser> | Guid | Non | TUser hérite de LgIdentityUserGuid |
LgApplicationTrackedChangeDbContext<TUser> | string | Oui | TUser hérite de LgIdentityUser |
LgApplicationTrackedChangeDbContextGuid<TUser> | Guid | Oui | TUser hérite de LgIdentityUserGuid |
LgApplicationDbContextBase<TUser, TRole, TKey> hérite de IdentityDbContext<TUser, TRole, TKey>, implémente ILgApplicationDbContext et expose les éléments communs comme Database, Eulas, SaveChangesAsync(...), Set<TEntity>() et LoadAnonymizerRules().
GuidLes applications Lagoon récentes utilisent souvent LgApplicationDbContextGuid<TUser> pour manipuler directement des identifiants Guid côté Identity.
Structure du contexte applicatif
Un contexte Lagoon configure le fournisseur EF Core dans une méthode statique Configure(...), appelle la configuration héritée dans OnModelCreating(...), puis ajoute les règles projet.
public class ApplicationDbContext : LgApplicationDbContextGuid<ApplicationUser>
{
internal protected const string CONNECTION_STRING_KEY = "SqliteDb";
public ApplicationDbContext(DbContextOptions options)
: base(options)
{ }
public ApplicationDbContext()
{ }
public static void Configure(DbContextOptionsBuilder builder, IConfiguration configuration, bool enableDetailedLogging = false)
{
// Configure le fournisseur EF Core et l'assembly qui contient les migrations.
builder.UseSqlite(
configuration.GetConnectionString(CONNECTION_STRING_KEY),
options => options.MigrationsAssembly(GetAssemblyName<ApplicationDbContext>()));
// Enregistre les jeux d'entités nécessaires à OpenIddict avec des clés Guid.
builder.UseOpenIddict<Guid>();
if (enableDetailedLogging)
{
// Active les détails utiles pendant les migrations et le diagnostic local.
builder.EnableDetailedErrors();
builder.EnableSensitiveDataLogging();
}
}
protected override void OnModelCreating(ModelBuilder builder)
{
// La configuration Lagoon/Identity doit être appliquée avant les règles projet.
base.OnModelCreating(builder);
SetUserNameRequired(builder);
SetUserEmailRequired(builder);
DisableCascadingDeletionBehavior(builder);
HasIdentityRoles<Roles>(builder);
}
protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder)
{
base.ConfigureConventions(configurationBuilder);
// Enregistre les dates en UTC et les recharge en heure locale.
configurationBuilder.DateSaveAsUtcLoadAsLocal();
}
}
UseOpenIddict<Guid>() obligatoireDepuis Lagoon 4.0, les entités OpenIddict utilisent toujours une clé primaire Guid, indépendamment du type de clé de ApplicationUser : un ApplicationUser : LgIdentityUser (clé string) doit lui aussi déclarer builder.UseOpenIddict<Guid>().
Le serveur force ce type de clé en dur ; un builder.UseOpenIddict() sans argument (clé string) fait échouer le démarrage de l'application avec InvalidOperationException: Cannot create a DbSet for 'OpenIddictEntityFrameworkCoreApplication'.
La mise à niveau lgn update réécrit automatiquement l'appel et génère la migration EF correspondante. Relisez cette migration avant de l'appliquer : la conversion string → Guid vide les tables OpenIddict (jetons et autorisations sont régénérés à la connexion, applications et scopes réamorcés au démarrage) et, sous SQL Server, libère puis recrée les clés primaires, clés étrangères et index portés par les colonnes converties.
Méthodes Lagoon utiles dans OnModelCreating
| Méthode | Rôle |
|---|---|
SetUserNameRequired(builder) | Rend UserName et NormalizedUserName obligatoires sur l'utilisateur Identity. |
SetUserEmailRequired(builder) | Rend Email et NormalizedEmail obligatoires sur l'utilisateur Identity. |
DisableCascadingDeletionBehavior(builder) | Force les relations EF Core en DeleteBehavior.NoAction. |
HasIdentityRoles<TAppRole>(builder) | Ajoute les rôles Identity à partir d'une énumération. |
UseNotifications<TNotification>(builder, ...) | Déclare les tables de notifications et d'association utilisateur. |
base.OnModelCreating(builder) doit rester le premier appel : il configure Identity, LgSettings, Eulas, la collation éventuelle et les entités internes Lagoon.
Interface ILgApplicationDbContext
ILgApplicationDbContext est le contrat commun utilisé par l'injection de dépendances. Il expose notamment :
| Membre | Usage |
|---|---|
Database | Accès aux opérations de base EF Core. |
Eulas | Table des conditions d'utilisation gérée par Lagoon. |
SaveChanges() / SaveChangesAsync(...) | Persistance EF Core. |
Set<TEntity>() | Accès générique à un DbSet<TEntity>. |
LoadAnonymizerRules() | Règles d'anonymisation utilisées par les exports de base. |
Suivi des modifications
Pour activer l'audit trail EF Core, le contexte hérite d'une variante LgApplicationTrackedChangeDbContext.... Les changements sont écrits dans la table LgTrackedChanges pour les entités suivies.
public class ApplicationDbContext : LgApplicationTrackedChangeDbContextGuid<ApplicationUser>
{
public ApplicationDbContext(DbContextOptions options, IHttpContextAccessor httpContextAccessor)
: base(options, httpContextAccessor)
{ }
}
Le suivi est piloté par les attributs EnableTrackedChangeAttribute et TrackedChangeAttribute. Les variantes suivies ajoutent aussi SaveChangesAsync(string actionDetails, CancellationToken cancellationToken = default) et la propriété TrackedChangeDisabled.
N'ajoutez pas de DbSet<TrackedChange> ou DbSet<TrackedChangeGuid> manuellement : les contextes LgApplicationTrackedChangeDbContext<TUser> et LgApplicationTrackedChangeDbContextGuid<TUser> déclarent l'entité d'audit.
Conventions de modèle
| Élément | Convention |
|---|---|
| Classe d'entité | Nom au singulier. |
DbSet | Nom au pluriel. |
| Clé primaire | Jamais nullable. |
| Chaîne | Définir une longueur maximale. |
| Booléen | Préfixe Is. |
| Date | Suffixe Date. |
| Navigation | Propriété virtual. |
| Snapshot de migration | Ne jamais modifier ApplicationDbContextModelSnapshot.cs à la main. |