web-dev-qa-db-fra.com

Pourquoi Entity Framework est plus rapide que Dapper dans une instruction de sélection directe

Je commence à utiliser ORM avec une base de données. Actuellement, je suis en train de créer un nouveau projet et je dois décider si j'utiliserai Entity Framework ou Dapper. J'ai lu de nombreux articles disant que Dapper est plus rapide qu'Entity Framework.

J'ai donc créé 2 projets prototypes simples, l'un utilisant Dapper, l'autre utilisant Entity Framework avec une fonction permettant d'obtenir toutes les lignes d'une table . Le schéma de la table est illustré ci-dessous.

Table Schema

et le code pour les deux projets comme suit

pour le projet Dapper

System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
sw.Start();
IEnumerable<Emp> emplist = cn.Query<Emp>(@"Select * From Employees");
sw.Stop();
MessageBox.Show(sw.ElapsedMilliseconds.ToString());

pour Entity Framework Project

System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
sw.Start();
IEnumerable<Employee> emplist = hrctx.Employees.ToList();
sw.Stop();
MessageBox.Show(sw.ElapsedMilliseconds.ToString());

après avoir essayé le code ci-dessus plusieurs fois seulement la première fois que j'exécute le projet, le code de Dapper sera plus rapide et, après cette première fois, j'obtiendrai toujours de meilleurs résultats avec le projet de structure d'entité arrêter le chargement paresseux

hrctx.Configuration.LazyLoadingEnabled = false;

mais toujours le même EF exécute plus rapide sauf pour la première fois.

Est-ce que quelqu'un peut me donner des explications ou des conseils sur ce qui rend EF plus rapide dans cet exemple, bien que tous les articles sur le Web disent le contraire

Mettre à jour

J'ai changé la ligne de code dans l'échantillon d'entité pour être

IEnumerable<Employee> emplist = hrctx.Employees.AsNoTracking().ToList();

l'utilisation de AsNoTracking comme mentionné dans certains articles arrête la mise en cache de l'entité et, après l'arrêt de la mise en cache, l'exemple de dapper fonctionne mieux (mais pas une très grande différence)

23
Ahmed

ORM (Object Relational Mapper) est un outil qui crée une couche entre votre application et la source de données et vous renvoie les objets relationnels au lieu de (En termes de c # que vous utilisez), objets ADO.NET. C'est la chose fondamentale que chaque ORM fait.

Pour ce faire, les ORM exécutent généralement la requête et map la DataReader renvoyée à la classe POCO. Dapper est limité jusqu'à ici.

Pour aller plus loin, certains ORM (également appelés "ORM complets") font beaucoup plus de choses, telles que générer une requête pour rendre votre base de données d'application indépendante, mettre en cache vos données pour les prochains appels, gérer l'unité de travail pour vous, etc. Ce sont tous de bons outils et ajoutent de la valeur à ORM; mais cela a un coût. Entity Framework entre dans cette classe.

Pour générer la requête, EF doit exécuter du code supplémentaire. Le cache améliore les performances, mais la gestion du cache nécessite l'exécution de code supplémentaire. Il en va de même pour l'unité de travail et toute autre fonctionnalité complémentaire fournie par EF. Tout ceci économise vous écrit un code supplémentaire et EF en paie le coût.

Et le coût est la performance. Comme Dapper fait un travail très basique, il est plus rapide. mais vous devez écrire plus de code. Comme EF fait beaucoup plus que cela, il est (un peu) plus lent; mais vous devez écrire moins de code.

Alors, pourquoi vos tests montrent des résultats opposés?
Parce que les tests que vous exécutez ne sont pas comparables.

Les ORM complets présentent de nombreuses fonctionnalités intéressantes, comme expliqué ci-dessus; L'un d'eux est UnitOfWork. Le suivi est l’une des responsabilités de UoW. Lorsque l'objet est demandé (requête SQL) pour la première fois, il provoque un aller-retour vers la base de données. Cet objet est ensuite enregistré dans la mémoire cache. Full ORM assure le suivi des modifications apportées à cet objet déjà chargé. Si le même objet est demandé à nouveau (autre requête SQL dans la même étendue UoW incluant un objet chargé), ils ne font pas l'aller-retour à la base de données. Au lieu de cela, ils renvoient l'objet du cache mémoire à la place. De cette façon, un temps considérable est économisé.
Dapper ne prend pas en charge cette fonctionnalité, ce qui la ralentit dans vos tests.

Cependant, cet avantage n'est applicable que si le même objet est chargé plusieurs fois. De même, si le nombre d'objets chargés en mémoire est trop élevé, l'ORM complet sera ralenti, car le temps nécessaire pour vérifier les objets en mémoire sera plus élevé. Encore une fois, cet avantage dépend du cas d'utilisation.

28
Amit Joshi

L'article Le benchmark de performances Entity Framework Core 2.0 vs Dapper, interrogeant les tables SQL Azure confirme que Dapper est un peu plus rapide, mais pas suffisant pour ignorer les avantages du "ORM complet".

1

Il n'y a pas de problème à les mélanger. Dans mon projet actuel, j'utilise Dapper pour sélectionner des données et EF pour créer et mettre à jour des migrations de bases de données. 

Dapper devient extrêmement utile quand il s'agit de requêtes complexes impliquant plus de deux tables ou impliquant des opérations complexes (jonction de plusieurs colonnes, jonction avec les clauses> = et <=, sélections récursives, cte, etc.) Le SQL pur est beaucoup plus facile que LINQ. Comme je le sais, Entity Framework (contrairement à Dapper) ne peut pas utiliser la méthode .FromSql () sur des DTO personnalisés. Il ne peut mapper qu'une seule table devant figurer dans le contexte de votre base de données.

1
Liam Kernighan

I read many articles which says that Dapper is faster than Entity Framework

Le problème avec la plupart des repères sur Internet est qu'ils comparent EF Linq à Dapper. Et c'est ce que vous avez fait aussi. Ce qui est injuste. Une requête générée automatiquement (EF) est souvent différente de celle écrite par un bon développeur.

Ce,

IEnumerable<Employee> emplist = hrctx.Employees.ToList();

devrait être remplacé par ceci.

IEnumerable<Employee> emplist = hrctx.Employees.FromSql(@"Select * From Employees").AsNoTracking();

Modifier:

Comme l'a souligné @mjwills, voici le tableau des résultats pour les instructions insert, update et select.

 enter image description here

Dapper surpasse EF Core 2. Cependant, on peut constater que pour les requêtes simples EF, la différence est très minime. J'ai posté détails complets ici .

0
Mohsin