Partager via


Mise à jour efficace

Traitement par lots

EF Core permet de minimiser les allers-retours en effectuant un traitement par lot automatique de toutes les mises à jour ensemble dans un seul aller-retour. Prenez en compte les éléments suivants :

var blog = context.Blogs.Single(b => b.Url == "http://someblog.microsoft.com");
blog.Url = "http://someotherblog.microsoft.com";
context.Add(new Blog { Url = "http://newblog1.microsoft.com" });
context.Add(new Blog { Url = "http://newblog2.microsoft.com" });
context.SaveChanges();

L’opération ci-dessus charge un blog à partir de la base de données, modifie son URL et ajoute ensuite deux nouveaux blogs. Pour appliquer ceci, deux instructions SQL INSERT et une instruction UPDATE sont envoyées vers la base de données. Au lieu de les envoyer une par une, comme des instances Blog sont ajoutées, EF Core suit ces changements de manière interne et les exécute dans un aller-retour unique quand SaveChanges est appelé.

Le nombre d’instructions que EF traite dans un seul aller-retour dépend du fournisseur de données utilisé. Par exemple, une analyse des performances a montré que le traitement par lot est généralement moins efficace pour SQL Server quand moins de 4 instructions sont impliquées. De la même manière, les avantages du traitement par lot se dégradent après environ 40 instructions pour SQL Server. EF Core exécute uniquement jusqu’à 42 instructions par défaut dans un seul traitement et exécute des instructions supplémentaires dans des allers-retours distincts.

Les utilisateurs peuvent également ajuster ces seuils pour atteindre des performances potentiellement plus élevées, mais effectuez une évaluation attentive avant de modifier ceux-ci :

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    optionsBuilder.UseSqlServer(
        @"Server=(localdb)\mssqllocaldb;Database=Blogging;Trusted_Connection=True",
        o => o
            .MinBatchSize(1)
            .MaxBatchSize(100));
}

Utiliser ExecuteUpdate et ExecuteDelete le cas échéant

Supposons que vous souhaitez donner une augmentation à tous vos employés. Une implémentation typique pour ceci dans EF Core ressemblera à ce qui suit :

foreach (var employee in context.Employees)
{
    employee.Salary += 1000;
}
context.SaveChanges();

Bien qu’il s’agisse d’un code parfaitement valide, analysons ce qu’il effectue du point de vue des performances :

  • Un aller-retour de base de données est effectué, pour charger tous les employés pertinents. Notez que cela réunit toutes les données de ligne Employés dans le client, même si le salaire uniquement est nécessaire.
  • Le suivi de changement d’EF Core crée des captures instantanées lors du chargement des entités, puis les compare aux instances pour découvrir les propriétés qui ont changées.
  • Généralement, un deuxième aller-retour de base de données est effectué pour enregistrer tous les changements (notez que certains fournisseurs de données fractionnent les changements en plusieurs allers-retours). Bien que ce comportement de traitement par lot est de loin meilleur à un aller-retour par mise à jour, EF Core envoie encore une instruction UPDATE par employé et la base de données doit exécuter chaque instruction séparément.

À compter d’EF Core 7.0, vous pouvez utiliser les méthodes ExecuteUpdate et ExecuteDelete pour effectuer la même chose de manière bien plus efficace :

context.Employees.ExecuteUpdate(s => s.SetProperty(e => e.Salary, e => e.Salary + 1000));

Cette opération envoie l’instruction SQL suivante à la base de données :

UPDATE [Employees] SET [Salary] = [Salary] + 1000;

Cette UPDATE effectue l’opération complète dans un seul aller-retour, sans charger ou envoyer des données réelles vers la base de données, et sans utiliser la machinerie de suivi des changements d’EF qui impose des frais supplémentaires. Pour plus d’informations, consultez ExecuteUpdate et ExecuteDelete.

Si vous utilisez une version plus ancienne d’EF Core qui ne prend pas encore en charge ExecuteUpdate et ExecuteDelete, ou si vous souhaitez exécuter une instruction SQL complexe qui n’est pas prise en charge par ces méthodes, vous pouvez encore utiliser une requête SQL pour effectuer l’opération :

context.Database.ExecuteSql($"UPDATE [Employees] SET [Salary] = [Salary] + 1000");

Pour en savoir plus sur les différences entre SaveChanges et ExecuteUpdate/ExecuteDelete, voir la page Vue d’ensemble sur l’enregistrement de données.