web-dev-qa-db-de.com

Warum Entity Framework in Direct-Select-Anweisungen schneller als Dapper ausgeführt wird

Ich bin neu im Umgang mit ORM im Umgang mit Datenbanken. Derzeit mache ich ein neues Projekt und muss entscheiden, ob ich Entity Framework oder Dapper verwenden werde. Ich habe viele Artikel gelesen, die besagen, dass Dapper schneller ist als Entity Framework.

Also habe ich zwei einfache Prototypprojekte erstellt, eines mit Dapper, und das andere verwendet Entity Framework mit einer Funktion, um alle Zeilen aus einer Tabelle zu holen. Das Tabellenschema ist das folgende Bild

Table Schema

und den Code für beide Projekte wie folgt

für das Dapper-Projekt

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());

für das Entity Framework-Projekt

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

nachdem ich den obigen Code viele Male ausprobiert habe, erst wenn ich das Projekt zum ersten Mal ausführte, wird der Dapper-Code schneller und nach diesem ersten Mal bekomme ich immer bessere Ergebnisse von Entity Framework-Projekt. __ Stoppen Sie das faule Laden

hrctx.Configuration.LazyLoadingEnabled = false;

aber die gleiche EF ist immer noch schneller, außer beim ersten Mal.

Kann mir jemand eine Erklärung oder Anleitung geben, was EF in diesem Beispiel schneller macht, obwohl alle Artikel im Web das Gegenteil besagen

Update

Ich habe die Codezeile im Entity-Sample geändert

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

durch die Verwendung von AsNoTracking wird, wie in einigen Artikeln erwähnt, die Zwischenspeicherung des Entity-Frameworks beendet. Nach dem Stoppen der Zwischenspeicherung funktioniert das Dapper-Beispiel besser (jedoch kein großer Unterschied)

23
Ahmed

ORM (Object Relational Mapper) ist ein Werkzeug, das Layer zwischen Ihrer Anwendung und Datenquelle erstellt und Ihnen die relationalen Objekte anstelle von (In Bezug auf die von Ihnen verwendeten c #) ADO.NET-Objekte zurückgibt. Dies ist eine grundlegende Sache, die jeder ORM tut.

Zu diesem Zweck führen ORMs im Allgemeinen die Abfrage und map die zurückgegebene DataReader für die POCO-Klasse aus. Dapper ist bis hier begrenzt.

Um dies weiter auszudehnen, führen einige ORMs (auch als "vollständiger ORM" bezeichnet) viel mehr durch, indem Sie eine Abfrage generieren, um Ihre Anwendungsdatenbank unabhängig zu machen, Ihre Daten für zukünftige Anrufe zwischenspeichern, Arbeitseinheiten verwalten und vieles mehr. All dies sind gute Werkzeuge und erhöhen den Wert von ORM. aber es geht mit kosten. Entity Framework fällt in diese Klasse.

Um die Abfrage zu generieren, muss EF zusätzlichen Code ausführen. Der Cache verbessert die Leistung, das Verwalten des Caches muss jedoch zusätzlichen Code ausführen. Gleiches gilt für Arbeitseinheiten und alle anderen von EF bereitgestellten Zusatzfunktionen. All dies erspart Sie, zusätzlichen Code zu schreiben, und EF übernimmt die Kosten.

Und das cost ist Leistung. Da Dapper sehr einfache Arbeit verrichtet, ist es schneller. aber Sie müssen mehr Code schreiben. Da EF viel mehr tut, ist es (etwas) langsamer. aber Sie müssen weniger Code schreiben.

Warum zeigen Ihre Tests also entgegengesetzte Ergebnisse?
Weil die Tests, die Sie ausführen, nicht vergleichbar sind.

Volle ORMs weisen viele gute Eigenschaften auf, wie oben erläutert. Eines davon ist UnitOfWork. Tracking ist eine der Aufgaben von UoW. Wenn das Objekt zum ersten Mal angefordert wird (SQL-Abfrage), führt dies zu einer Rundfahrt zur Datenbank. Dieses Objekt wird dann im Speichercache gespeichert. Full ORM verfolgt die Änderungen, die an diesen bereits geladenen Objekten vorgenommen wurden. Wenn dasselbe Objekt erneut angefordert wird (andere SQL-Abfragen im selben UoW-Bereich, die ein geladenes Objekt enthalten), führen sie keine Datenbankrundfahrt durch. Stattdessen geben sie das Objekt stattdessen aus dem Cache-Speicher zurück. Auf diese Weise wird viel Zeit gespart.
Dapper unterstützt diese Funktion nicht, weshalb sie in Ihren Tests langsamer arbeitet.

Dieser Vorteil ist jedoch nur anwendbar, wenn die gleichen Objekte mehrfach geladen wurden. Wenn die Anzahl der in den Speicher geladenen Objekte zu hoch ist, wird der gesamte ORM-Wert verlangsamt, da die Zeit, die erforderlich ist, um die Objekte im Speicher check zu überprüfen, höher ist. Dieser Nutzen hängt also wiederum vom Anwendungsfall ab.

28
Amit Joshi

Der Artikel Entity Framework Core 2.0 im Vergleich zu Dapper-Leistungsbenchmark zum Abfragen von SQL Azure-Tabellen bestätigt, dass Dapper etwas schneller ist, aber nicht ausreicht, um die Vorteile des "vollen ORM" zu ignorieren.

1

Es ist kein Problem, sie miteinander zu mischen. In meinem aktuellen Projekt verwende ich Dapper zum Auswählen von Daten und EF zum Erstellen und Aktualisieren sowie Datenbankmigrationen. 

Dapper ist äußerst hilfreich, wenn es um komplexe Abfragen geht, bei denen mehr als zwei Tabellen beteiligt sind oder wenn es komplexe Vorgänge gibt (Zusammenfügen mit mehr als einer Spalte, Zusammenfügen mit> = und <= Klauseln, rekursive Auswahlen, Cte's usw.) Pure SQL ist viel einfacher als LINQ. Wie ich weiß, kann Entity Framework (. Im Gegensatz zu Dapper) die .FromSql () - Methode nicht für benutzerdefinierte DTOs verwenden. Es kann nur eine Tabelle zuordnen, die sich in Ihrem Datenbankkontext befinden sollte.

1
Liam Kernighan

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

Bei den meisten Benchmarks im Internet besteht das Problem darin, dass sie EF Linq mit Dapper vergleichen. Und das hast du auch getan. Welches ist unfair. Eine automatisch generierte Abfrage (EF) ist häufig nicht gleich der von einem guten Entwickler geschriebenen.

Diese,

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

sollte dadurch ersetzt werden.

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

Bearbeiten:

Wie von @mjwills dargelegt, ist unten die Ergebnistabelle für insert, update und select-Anweisungen.

 enter image description here

Dapper ist EF Core 2 überlegen. Bei EF-Abfragen ist der Unterschied jedoch sehr gering. Ich habe komplette Details hier gepostet .

0
Mohsin