0

I recently determined que l'utilisation d'un DbContext Dependency Injected dans .NET Core et l'utilisation d'appels async await ne génèrent aucun gain de performance significatif par rapport à la création d'un nouveau DbContext chaque fois que je souhaite accéder à la base de données.Pourquoi créer un nouveau DbContext plus lent que celui de Dependency Injecté?

Mais maintenant j'ai besoin de savoir pourquoi.

J'ai fait un test beaucoup plus granulaire avec System.Diagnostics.Stopwatch dans mes services API .NET Core 1.1 (que le contrôleur appelle) dans lequel j'ai exécuté le chronomètre uniquement lors de l'accès à la base de données. Les résultats étaient surprenants.

Lorsque vous utilisez la norme contexte Injecté de dépendance et async/appels: attendent

var task1 = _InjectedDbContext.Table1.FirstOrDefaultAsync(p => p.Id == SomeId); 
var task2 = _InjectedDbContext.Table2.Where(u => u.AnotherId == SomeOtherId).ToListAsync(); 

(var result1, var result2) = await (task1, task2).WhenAll(); 

chaque requête DbContext a duré sensiblement moins de 100 ms.

Cependant, lorsque vous utilisez cette méthode:

using (var context = new DbContext(_InjectedContextOptions.Options)) 
{ 
    var task1 = context.Table1.FirstOrDefaultAsync(p => p.Id == SomeId); 
    var task2 = context.Table2.Where(u => u.AnotherId == SomeOtherId).ToListAsync(); 

    (var result1, var result2) = await (task1, task2).WhenAll(); 
} 

Chaque requête DbContext ont duré de 100-230 ms.

Pour votre information, voici mon code pour la configuration de DI dans Startup.cs ConfigureServices:

var connection = Configuration.GetConnectionString("mydb"); 
services.AddDbContext<MyDbContext>(options => options.UseSqlServer(connection)); 

Et voici mon code pour fournir les DbContextOptions comme singleton chaque fois que je crée une nouvelle DbContext:

var dbContextOptions = new DbContextOptionsBuilder<MyDbContext>();   
dbContextOptions.UseSqlServer(Configuration.GetConnectionString("MyDb")); 
services.AddSingleton(dbContextOptions); 

J'ai également déterminé que le décalage n'est pas causé simplement par la création de DbContext dans l'instruction using (qui est une opération très rapide). Qu'est-ce qui se passe ici? Est-il essayer de se reconnecter à la DB à chaque fois ou quelque chose?

+0

Comment avez-vous enregistré votre DbContext? Parce que le DI peut contenir une copie du DbContext en mémoire pour la durée de l'application. la demande ou un appel repose sur le périmètre que vous avez enregistré avec DbContext. Cela expliquerait le gain de performance. –

+0

Salut, bonne question. J'ai mis à jour ma question avec le code pour le DI dans les deux cas. La durée de vie est à la valeur par défaut: https://stackoverflow.com/questions/37507691/entity-framework-core-service-default-lifetime – starmandeluxe

+0

@RickvandenBosch: l'enregistrement par défaut pour AddDbContext est défini, donc il est résolu par requête, de sorte que shouldn ne sois pas.Avez-vous par hasard créer un grand nombre d'instances DbContext lors d'une seule requête? DbContext recycle généralement les connexions, mais si vous créez un grand nombre de connexions, cela peut être la raison pour cela – Tseng

Répondre

0

Vous utilisez la méthode AddDbContext, pour le DbContext que vous utilisez dans le premier scénario, qui ajoute le DbContext aux services Scoped (si je ne me trompe pas). Le DbContext est probablement initialisé dès que le service est ajouté en raison de l'optimisation (pas sûr ici). Dans le second cas, vous créez un nouveau DbContext. En dehors de la création de DbContext, il y a aussi d'autres choses à faire.

Extrait de this post, voici quelques conseils pour «warm-up de votre contexte:

  1. En utilisant un modèle DB cache magasin
  2. Générer des vues pré-compilés
  3. Générer version pré-compilée de entityframework utilisant n-gen pour éviter la juxtaposition

Les conseils ci-dessus indiquent que l'utilisation d'un contexte DbContext ne se limite pas à la création d'un contexte DbContext.

+0

Je suis d'accord avec votre premier point sur l'initialisation avec DI. Mais je ne suis pas sûr de ces optimisations: cela ne va-t-il pas améliorer les performances avec les deux méthodes que j'ai présentées ici, pas seulement la nouvelle méthode de contexte? Je suis plus intéressé à expliquer la différence entre les deux, pas des conseils généraux pour augmenter les performances EF. En outre, je n'ai référencé que la création de DbContext et c'est un hit de performance très insignifiant ... – starmandeluxe

+0

Salut @starmandeluxe, comme je le disais plus haut: Je peux imaginer qu'il y a une certaine optimisation dans la méthode AddDbContext qui fait que le scénario DI soit plus rapide . Les conseils ne sont là que pour montrer qu'il y a de la place pour améliorer les performances, celles-ci peuvent déjà être implémentées dans la méthode AddDbContext, ce qui les rend plus rapides que de les créer vous-même. –

+0

@RickvandenBosch Je pense que le problème réside dans la façon dont les choses sont chronométrées. – Mardoxx