ASP.NET Core Blazor avec Entity Framework Core (EF Core)
Remarque
Ceci n’est pas la dernière version de cet article. Pour la version actuelle, consultez la version .NET 9 de cet article.
Avertissement
Cette version d’ASP.NET Core n’est plus prise en charge. Pour plus d’informations, consultez la stratégie de support .NET et .NET Core. Pour la version actuelle, consultez la version .NET 9 de cet article.
Important
Ces informations portent sur la préversion du produit, qui est susceptible d’être en grande partie modifié avant sa commercialisation. Microsoft n’offre aucune garantie, expresse ou implicite, concernant les informations fournies ici.
Pour la version actuelle, consultez la version .NET 9 de cet article.
Cet article explique comment utiliser Entity Framework Core (EF Core) dans les applications Blazor côté serveur.
Blazor côté serveur est un framework d’application avec état. L’application maintient une connexion continue au serveur, et l’état de l’utilisateur est conservé dans la mémoire du serveur dans un circuit. Des données conservées dans des instances de service d’injection de dépendances qui sont limitées au circuit constituent un exemple d’état utilisateur. Le modèle d’application unique fourni par Blazor nécessite une approche spéciale pour utiliser Entity Framework Core.
Remarque
Cet article aborde EF Core dans les applications Blazor côté serveur. Les applications Blazor WebAssembly s’exécutent dans un bac à sable (sandbox) WebAssembly qui empêche la plupart des connexions de base de données directes. L’exécution d’EF Core dans Blazor WebAssembly n’entre pas dans le cadre de cet article.
Cette aide s’applique aux composants qui adoptent le rendu côté serveur interactif (SSR interactif) dans une Blazor Web App.
Cette aide s’applique au projet Server
d’une solution Blazor WebAssembly hébergée ou d’une application Blazor Server.
Flux d’authentification sécurisé requis pour les applications de production
Cet article concerne l’utilisation d’une base de données locale qui ne nécessite pas d’authentification utilisateur. Les applications de production doivent utiliser le flux d’authentification le plus sécurisé disponible. Pour plus d’informations sur l’authentification pour les applications de test et de production Blazor déployées, consultez les articles dans le nœud Sécurité et BlazorIdentity.
Pour les services Microsoft Azure, nous vous recommandons d’utiliser des identités managées. Les identités managées offrent un moyen sécurisé de s’authentifier auprès des services Azure sans stocker d’informations d’identification dans le code de l’application. Pour plus d’informations, consultez les ressources suivantes :
- Que sont les identités managées pour les ressources Azure ? (Documentation Microsoft Entra)
- Documentation sur les services Azure
Créer un didacticiel sur l’application Blazor de base de données de films
Pour obtenir une expérience de didacticiel générant une application qui utilise EF Core pour les opérations de base de données, consultez Créer une application de base de données vidéo Blazor (Vue d’ensemble). Le tutoriel vous montre comment créer un Blazor Web App qui peut afficher et gérer des films dans une base de données de films.
Accès aux bases de données
EF Core s’appuie sur un DbContext comme moyen de configurer l’accès à la base de données et d’agir comme une unité de travail. EF Core fournit l’extension AddDbContext pour les applications ASP.NET Core qui inscrit le contexte en tant que service avec étendue. Dans les applications Blazor côté serveur, les inscriptions de service délimité peuvent être problématiques, car l’instance est partagée entre les composants du circuit de l’utilisateur. DbContext n’est pas thread-safe et n’est pas conçu pour une utilisation simultanée. Les durées de vie existantes sont inappropriées pour les raisons suivantes :
- Singleton partage l’état entre tous les utilisateurs de l’application et conduit à une utilisation simultanée inappropriée.
- Délimité (valeur par défaut) pose un problème similaire entre les composants pour le même utilisateur.
- Temporaire entraîne la création d’une instance par requête. Toutefois, comme les composants peuvent être de longue durée, il en résulte un contexte d’une plus longue durée que prévu.
Les recommandations suivantes sont conçues pour fournir une approche cohérente de l’utilisation d’EF Core dans les applications Blazor côté serveur.
Envisagez d’utiliser un seul contexte par opération. Le contexte est conçu pour une instanciation rapide et à faible charge :
using var context = new ProductsDatabaseContext(); return await context.Products.ToListAsync();
Utilisez un indicateur pour empêcher plusieurs opérations simultanées :
if (Loading) { return; } try { Loading = true; ... } finally { Loading = false; }
Placez les opérations de base de données après la ligne de
Loading = true;
dans le bloctry
.La logique de chargement ne nécessite pas de verrouillage des enregistrements de la base de données, car la cohérence des threads n’est pas un problème. La logique de chargement est utilisée pour désactiver les contrôles d’interface utilisateur afin que les utilisateurs ne sélectionnent pas par inadvertance des boutons ou ne mettent pas à jour les champs pendant la récupération de données.
S’il est possible que plusieurs threads accèdent au même bloc de code, injectez une fabrique et créez une nouvelle instance par opération. Autrement, l’injection et l’utilisation du contexte sont généralement suffisantes.
Pour les opérations de plus longue durée qui tirent parti du EF Core ou du contrôle d’accès concurrentiel, d’, limitez le contexte à la durée de vie du composant.
Nouvelles instances DbContext
Le moyen le plus rapide de créer une instance DbContext consiste à utiliser new
. Toutefois, certains scénarios nécessitent la résolution de dépendances supplémentaires :
- Utilisation d’
DbContextOptions
pour configurer le contexte. - Utilisation d’une chaîne de connexion par DbContext, comme lorsque vous utilisez le modèle Identity d’ASP.NET Core. Pour plus d’informations, consultez Architecture multilocataire (documentation EF Core).
Avertissement
Ne stockez pas les secrets d’application, les chaîne de connexion, les informations d’identification, les mots de passe, les numéros d’identification personnels (PIN), le code C#/.NET privé ou les clés/jetons privés dans le code côté client, qui est toujours non sécurisé. Dans les environnements de test/intermédiaire et de production, le code côté Blazor serveur et les API web doivent utiliser des flux d’authentification sécurisés qui évitent de conserver les informations d’identification dans le code du projet ou les fichiers de configuration. En dehors des tests de développement locaux, nous vous recommandons d’éviter l’utilisation de variables d’environnement pour stocker des données sensibles, car les variables d’environnement ne sont pas l’approche la plus sécurisée. Pour les tests de développement locaux, l’outil Secret Manager est recommandé pour sécuriser les données sensibles. Pour plus d’informations, consultez Gestion sécurisée des données sensibles et des informations d’identification.
L’approche recommandée pour créer un DbContext avec des dépendances consiste à utiliser une fabrique. EF Core 5.0 ou version ultérieure fournit une fabrique intégrée pour la création de contextes.
Dans les versions de .NET antérieures à la version 5.0, utilisez les DbContextFactory
suivantes :
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
namespace BlazorServerDbContextExample.Data
{
public class DbContextFactory<TContext>
: IDbContextFactory<TContext> where TContext : DbContext
{
private readonly IServiceProvider provider;
public DbContextFactory(IServiceProvider provider)
{
this.provider = provider ?? throw new ArgumentNullException(
$"{nameof(provider)}: You must configure an instance of " +
"IServiceProvider");
}
public TContext CreateDbContext() =>
ActivatorUtilities.CreateInstance<TContext>(provider);
}
}
Dans la fabrique précédente :
- ActivatorUtilities.CreateInstance satisfait toutes les dépendances via le fournisseur de services.
- IDbContextFactory<TContext> est disponible dans EF Core ASP.NET Core 5.0 ou version ultérieure. L’interface précédente n’est donc requise que pour ASP.NET Core 3.x.
L’exemple suivant configure SQLite et active la journalisation des données dans une application qui gère les contacts. Le code utilise une méthode d’extension (AddDbContextFactory) afin de configurer la fabrique de base de données pour l’injection de dépendances et de fournir des options par défaut :
builder.Services.AddDbContextFactory<ContactContext>(opt =>
opt.UseSqlite($"Data Source={nameof(ContactContext.ContactsDb)}.db"));
services.AddDbContextFactory<ContactContext>(opt =>
opt.UseSqlite($"Data Source={nameof(ContactContext.ContactsDb)}.db"));
La fabrique est injectée dans des composants pour créer de nouvelles instances DbContext.
Définissez l'étendue d'un contexte de base de données pour une méthode de composant
La fabrique est injectée dans le composant :
@inject IDbContextFactory<ContactContext> DbFactory
Créez une DbContext pour une méthode utilisant la fabrique (DbFactory
) :
private async Task DeleteContactAsync()
{
using var context = DbFactory.CreateDbContext();
if (context.Contacts is not null)
{
var contact = await context.Contacts.FirstAsync(...);
if (contact is not null)
{
context.Contacts?.Remove(contact);
await context.SaveChangesAsync();
}
}
}
Limitez la portée d'un contexte de base de données à la durée de vie du composant
Vous pouvez souhaiter créer un DbContext qui existe pendant toute la durée de vie d’un composant. Cela vous permet de l’utiliser comme unité de travail et de tirer parti des fonctionnalités intégrées, telles que le suivi des modifications et la résolution de l’accès concurrentiel.
Implémentez IDisposable et injectez la fabrique dans le composant :
@implements IDisposable
@inject IDbContextFactory<ContactContext> DbFactory
Établissez une propriété pour la DbContext :
private ContactContext? Context { get; set; }
OnInitializedAsync
est remplacé pour créer la DbContext :
protected override async Task OnInitializedAsync()
{
Context = DbFactory.CreateDbContext();
}
La DbContext est supprimée lorsque le composant est supprimé :
public void Dispose() => Context?.Dispose();
Activer la journalisation des données sensibles
EnableSensitiveDataLogging inclut les données d’application dans les messages d’exception et la journalisation d’infrastructure. Les données journalisées peuvent inclure les valeurs attribuées aux propriétés des instances d’entité et les valeurs de paramètres pour les commandes envoyées à la base de données. La journalisation des données avec EnableSensitiveDataLogging présente un risque de sécurité, car elle peut exposer des mots de passe et d’autres Informations d’identification personnelle (PII) lors de la journalisation d’instructions SQL exécutées sur la base de données.
Nous vous recommandons d’activer EnableSensitiveDataLogging uniquement pour le développement et le test :
#if DEBUG
services.AddDbContextFactory<ContactContext>(opt =>
opt.UseSqlite($"Data Source={nameof(ContactContext.ContactsDb)}.db")
.EnableSensitiveDataLogging());
#else
services.AddDbContextFactory<ContactContext>(opt =>
opt.UseSqlite($"Data Source={nameof(ContactContext.ContactsDb)}.db"));
#endif