Aller au contenu principal

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 baseType de clé utilisateur/rôleSuivi des modificationsContrainte utilisateur
LgApplicationDbContext<TUser>stringNonTUser hérite de LgIdentityUser
LgApplicationDbContextGuid<TUser>GuidNonTUser hérite de LgIdentityUserGuid
LgApplicationTrackedChangeDbContext<TUser>stringOuiTUser hérite de LgIdentityUser
LgApplicationTrackedChangeDbContextGuid<TUser>GuidOuiTUser 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().

astuce
Clés Guid

Les 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.

ApplicationDbContext.cs
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();
}
}
attention
Clé OpenIddict : UseOpenIddict<Guid>() obligatoire

Depuis 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éthodeRô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 :

MembreUsage
DatabaseAccès aux opérations de base EF Core.
EulasTable 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.

ApplicationDbContext.cs
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.

Entités suivies

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émentConvention
Classe d'entitéNom au singulier.
DbSetNom au pluriel.
Clé primaireJamais nullable.
ChaîneDéfinir une longueur maximale.
BooléenPréfixe Is.
DateSuffixe Date.
NavigationPropriété virtual.
Snapshot de migrationNe jamais modifier ApplicationDbContextModelSnapshot.cs à la main.

Voir aussi​