it-swarm.com.de

Ist das Entity Framework für stark frequentierte Websites geeignet?

Ist Entity Framework 4 eine gute Lösung für eine öffentliche Website mit potenziell 1000 Treffern/Sekunde?

Nach meinem Verständnis ist EF eine praktikable Lösung für meist kleinere oder Intranet-Websites, lässt sich jedoch nicht einfach für eine beliebte Community-Website skalieren (ich weiß SO verwendet LINQ to SQL, aber ..). Ich hätte gerne mehr Beispiele/Beweise ...)

Jetzt stehe ich am Scheideweg, entweder einen reinen ADO.NET-Ansatz oder EF4 zu wählen. Denken Sie, dass die verbesserte Entwicklerproduktivität mit EF den Leistungsverlust und den detaillierten Zugriff von ADO.NET (mit gespeicherten Prozeduren) wert ist? Gibt es ernsthafte Probleme, mit denen eine stark frequentierte Website konfrontiert sein könnte? Wurde EF verwendet?

Vielen Dank im Voraus.

177
niaher

Es hängt ein bisschen davon ab, wie viel Abstraktion Sie brauchen. Alles ist ein Kompromiss; Zum Beispiel bieten EF und NHibernate eine große Flexibilität bei der Darstellung der Daten in interessanten und exotischen Modellen - aber als Ergebnis erhöhen sie den Overhead. Auffälliger Overhead.

Wenn Sie nicht brauchen, um zwischen Datenbankanbietern und verschiedenen Tabellenlayouts pro Client wechseln zu können, und wenn Ihre Daten hauptsächlich gelesen werden , und wenn Sie nicht in der Lage sein müssen, dasselbe Modell in EF, SSRS, ADO.NET Data Services usw. zu verwenden, können Sie weit gehen, wenn Sie absolute Leistung als Schlüsselmaßnahme wünschen schlimmer als auf dapper zu schauen. In unseren Tests, die sowohl auf LINQ-to-SQL als auch auf EF basieren, stellen wir fest, dass EF in Bezug auf die rohe Leseleistung signifikant langsamer ist, vermutlich aufgrund der Abstraktionsschichten (zwischen Speichermodell usw.) und Materialisierung.

Hier bei SO sind wir zwanghaft in Bezug auf die Rohleistung und freuen uns, den Entwicklungshit des Verlusts von Abstraktion in Kauf zu nehmen, um an Geschwindigkeit zu gewinnen. Daher ist unser primäres Tool zum Abfragen der Datenbank dapper . Dies ermöglicht es uns sogar, unser bereits vorhandenes LINQ-to-SQL-Modell zu verwenden, aber einfach: Es ist viel schneller. Bei Leistungstests entspricht dies im Wesentlichen genau der Leistung beim manuellen Schreiben des gesamten ADO.NET-Codes (Parameter, Datenleser usw.), jedoch ohne das Risiko, dass ein Spaltenname falsch ist. Es basiert jedoch auf SQL (obwohl es gerne SPROCs verwendet, wenn dies das von Ihnen gewählte Gift ist). Dies hat den Vorteil, dass keine zusätzliche Verarbeitung erforderlich ist, aber ist ein System für Leute, die SQL mögen . Was ich denke: keine schlechte Sache!

Eine typische Abfrage könnte beispielsweise sein:

int customerId = ...
var orders = connection.Query<Order>(
    "select * from Orders where CustomerId = @customerId ",
    new { customerId }).ToList();

das ist praktisch, spritzwassergeschützt usw. - aber ohne jede Menge Datenleser. Beachten Sie, dass es zwar sowohl horizontale als auch vertikale Partitionen zum Laden komplexer Strukturen verarbeiten kann, jedoch kein verzögertes Laden unterstützt (aber: Wir sind große Fans des sehr expliziten Ladens - weniger Überraschungen).

Beachten Sie in dieser Antwort, dass EF nicht für großvolumige Arbeiten geeignet ist. einfach: Ich weiß, dass der Dapper es zulässt.

152
Marc Gravell

Die Frage "Welches ORM soll ich verwenden?" Befasst sich wirklich mit der Spitze eines riesigen Eisbergs, wenn es um die allgemeine Datenzugriffsstrategie und die Leistungsoptimierung in einer Großanwendung geht.

Alle folgenden Dinge ( ungefähr in der Reihenfolge ihrer Wichtigkeit) wirken sich auf den Durchsatz aus, und alle werden (manchmal auf unterschiedliche Weise) von den meisten wichtigen ORM-Frameworks auf dem Markt behandelt:

  1. Datenbankdesign und -wartung

    Dies ist mit großem Abstand die wichtigste Determinante für den Durchsatz einer datengesteuerten Anwendung oder Website und wird von Programmierern häufig völlig ignoriert.

    Wenn Sie keine geeigneten Normalisierungstechniken verwenden, ist Ihre Site zum Scheitern verurteilt. Wenn Sie keine Primärschlüssel haben, ist fast jede Abfrage langsam. Wenn Sie bekannte Anti-Patterns verwenden, z. B. die Verwendung von Tabellen für Schlüsselwertpaare (AKA-Entitätsattributwert) ohne guten Grund, wird die Anzahl der physischen Lese- und Schreibvorgänge explodieren.

    Wenn Sie die von der Datenbank bereitgestellten Funktionen nicht nutzen, z. B. Seitenkomprimierung, FILESTREAM Speicher (für Binärdaten), SPARSE Spalten, hierarchyid für Hierarchien, und so weiter (alle SQL Server-Beispiele), dann werden Sie nicht annähernd die Leistung sehen, die Sie könnten sehen.

    Sie sollten sich Gedanken über Ihre Datenzugriffsstrategie machen nach Sie haben Ihre Datenbank entworfen und sich davon überzeugt, dass sie zumindest vorerst so gut wie möglich ist.

  2. Eifrig vs. Lazy Loading

    Die meisten ORMs verwendeten eine Technik namens Lazy Loading für Beziehungen. Dies bedeutet, dass standardmäßig jeweils eine Entität (Tabellenzeile) geladen wird und jedes Mal ein Roundtrip zur Datenbank durchgeführt wird muss eine oder mehrere verwandte (Fremdschlüssel-) Zeilen laden.

    Dies ist keine gute oder schlechte Sache, sondern hängt vielmehr davon ab, was tatsächlich mit den Daten geschehen soll und wie viel Sie im Voraus wissen. Manchmal ist Lazy-Loading absolut das Richtige. NHibernate kann beispielsweise entscheiden, überhaupt nichts abzufragen und einfach einen Proxy für eine bestimmte ID generieren. Wenn Sie nur die ID selbst benötigen, warum sollte sie dann mehr verlangen? Wenn Sie dagegen versuchen, einen Baum jedes einzelnen Elements in einer 3-Ebenen-Hierarchie zu drucken, wird das verzögerte Laden zu einer O (N²) -Operation, die extrem schlecht für die Leistung ist .

    Ein interessanter Vorteil bei der Verwendung von "reinem SQL" (d. H. Rohe ADO.NET-Abfragen/gespeicherte Prozeduren) besteht darin, dass Sie grundsätzlich darüber nachdenken müssen, welche Daten für die Anzeige eines bestimmten Bildschirms oder einer bestimmten Seite erforderlich sind. ORMs und Lazy-Loading-Funktionen können Sie nicht verhindern, aber sie tun geben Ihnen die Möglichkeit, ... nun, lazy und explodieren versehentlich die Anzahl der von Ihnen ausgeführten Abfragen. Sie müssen also die Funktionen zum Laden Ihrer ORMs verstehen und stets wachsam sein, wie viele Anfragen Sie für eine bestimmte Seitenanforderung an den Server senden.

  3. Caching

    Alle wichtigen ORMs verwalten einen Cache der ersten Ebene, den "Identitätscache" der AKA. Wenn Sie dieselbe Entität zweimal anhand ihrer ID anfordern, ist kein zweiter Roundtrip erforderlich, und auch (wenn Sie Ihre Datenbank korrekt entworfen haben) ) gibt Ihnen die Möglichkeit, optimistische Parallelität zu verwenden.

    Der L1-Cache ist in L2S und EF ziemlich undurchsichtig. Man muss darauf vertrauen, dass er funktioniert. NHibernate ist expliziter (Get/Load vs. Query/QueryOver). Solange Sie versuchen, so viel wie möglich nach ID abzufragen, sollten Sie hier in Ordnung sein. Viele Leute vergessen den L1-Cache und suchen wiederholt dieselbe Entität immer wieder anhand einer anderen ID als der ID (d. H. Eines Suchfelds). Wenn Sie dies tun müssen, sollten Sie die ID oder sogar die gesamte Entität für zukünftige Suchvorgänge speichern.

    Es gibt auch einen Level 2 Cache ("Query Cache"). NHibernate hat dies eingebaut. Linq to SQL und Entity Framework haben kompilierte Abfragen , was dazu beitragen kann, die Auslastung des App-Servers erheblich zu verringern, indem der Abfrageausdruck selbst kompiliert wird, die Daten jedoch nicht zwischengespeichert werden. Microsoft scheint dies eher als Anwendungsproblem als als Datenzugriffsproblem zu betrachten, und dies ist eine große Schwachstelle von L2S und EF. Unnötig zu erwähnen, dass dies auch eine Schwachstelle von "rohem" SQL ist. Um mit praktisch jedem anderen ORM als NHibernate eine wirklich gute Leistung zu erzielen, müssen Sie Ihre eigene Caching-Fassade implementieren.

    Es gibt auch eine L2-Cache- "Erweiterung" für EF4, die okay ist, aber nicht wirklich ein Ersatz für einen Cache auf Anwendungsebene.

  4. Anzahl der Abfragen

    Relationale Datenbanken basieren auf Mengen Daten. Sie sind wirklich gut darin, in kurzer Zeit groß Datenmengen zu produzieren, aber sie sind in Bezug auf die Abfrage bei weitem nicht so gut Latenz weil Mit jedem Befehl ist ein gewisser Overhead verbunden. Eine gut gestaltete App sollte die Stärken dieses DBMS nutzen und versuchen, die Anzahl der Abfragen zu minimieren und die Datenmenge in jedem zu maximieren.

    Jetzt sage ich nicht, dass Sie die gesamte Datenbank abfragen sollen, wenn Sie nur eine Zeile benötigen. Was ich sage ist, wenn Sie die Zeilen Customer, Address, Phone, CreditCard und Order benötigen Um eine einzelne Seite zu bedienen, sollten Sie zur gleichen Zeit fragen für alle gleichzeitig ausführen und nicht jede Abfrage einzeln ausführen. Manchmal ist es schlimmer als das, Sie werden Code sehen, der den gleichen Customer Datensatz 5 Mal hintereinander abfragt, zuerst um den Id, dann den Name, dann den EmailAddress, dann ... ist es lächerlich ineffizient.

    Selbst wenn Sie mehrere Abfragen ausführen müssen, die alle mit völlig unterschiedlichen Datensätzen arbeiten, ist es normalerweise noch effizienter, alles als ein einziges "Skript" an die Datenbank zu senden und mehrere Ergebnismengen zurückgeben zu lassen. Es ist der Overhead, mit dem Sie sich befassen, nicht die Gesamtdatenmenge.

    Dies mag nach gesundem Menschenverstand klingen, aber es ist oft sehr leicht, den Überblick über alle Abfragen zu verlieren, die in verschiedenen Teilen der Anwendung ausgeführt werden. Ihr Mitgliedschaftsanbieter fragt die Benutzer-/Rollentabellen ab, Ihre Kopfzeilenaktion fragt den Warenkorb ab, Ihre Menüaktion fragt die Site-Map-Tabelle ab, Ihre Seitenleistenaktion fragt die Liste der vorgestellten Produkte ab, und dann ist Ihre Seite möglicherweise in einige separate autonome Bereiche unterteilt, die Fragen Sie die Tabellen "Bestellverlauf", "Zuletzt angezeigt", "Kategorie" und "Inventar" separat ab. Bevor Sie dies wissen, führen Sie 20 Abfragen aus, bevor Sie überhaupt mit der Bereitstellung der Seite beginnen können. Es zerstört nur die Leistung.

    Einige Frameworks - und ich denke hier hauptsächlich an NHibernate - sind unglaublich clever und ermöglichen es Ihnen, etwas namens futures zu verwenden, das ganze Abfragen stapelt und schließlich versucht, sie alle gleichzeitig auszuführen mögliche Minute. AFAIK, Sie sind allein, wenn Sie dies mit einer der Microsoft-Technologien tun möchten. Sie müssen es in Ihre Anwendungslogik einbauen.

  5. Indizierung, Prädikate und Projektionen

    Mindestens 50% der Entwickler, mit denen ich spreche, und sogar einige Datenbankadministratoren scheinen Probleme mit dem Konzept der Abdeckung von Indizes zu haben. Sie denken: "Nun, die Spalte Customer.Name Ist indiziert, daher sollte jede Suche, die ich nach dem Namen mache, schnell sein." Außer es funktioniert nicht so, es sei denn, der Name Index deckt die spezifische Spalte ab, nach der Sie suchen. In SQL Server erfolgt dies mit INCLUDE in der Anweisung CREATE INDEX.

    Wenn Sie SELECT * Naiv überall verwenden - und das ist mehr oder weniger das, was jeder ORM tut, sofern Sie nicht ausdrücklich etwas anderes mit einer Projektion angeben -, kann das DBMS Ihre Indizes sehr gut ignorieren, da sie nicht abgedeckt sind Säulen. Eine Projektion bedeutet zum Beispiel, anstatt dies zu tun:

    from c in db.Customers where c.Name == "John Doe" select c
    

    Sie tun dies stattdessen:

    from c in db.Customers where c.Name == "John Doe"
    select new { c.Id, c.Name }
    

    Und dies wird für die meisten modernen ORMs anweisen, nur die Spalten Id und Name abzufragen, die vermutlich vom Index abgedeckt werden (aber nicht die Spalten Email, LastActivityDate oder welche anderen Spalten auch immer Sie dort eingefügt haben).

    Es ist auch sehr einfach, alle Indizierungsvorteile durch die Verwendung unangemessener Prädikate vollständig zu beseitigen. Zum Beispiel:

    from c in db.Customers where c.Name.Contains("Doe")
    

    ... sieht fast identisch mit unserer vorherigen Abfrage aus, führt jedoch tatsächlich zu einem vollständigen Tabellen- oder Index-Scan, da er in LIKE '%Doe%' übersetzt wird. Ebenso ist eine andere Abfrage, die verdächtig einfach aussieht ,:

    from c in db.Customers where (maxDate == null) || (c.BirthDate >= maxDate)
    

    Angenommen, Sie haben einen Index für BirthDate, hat dieses Prädikat eine gute Chance, es vollständig unbrauchbar zu machen. Unser hypothetischer Programmierer hier hat offensichtlich versucht, eine Art dynamische Abfrage zu erstellen ("Filtern Sie das Geburtsdatum nur, wenn dieser Parameter angegeben wurde"), aber dies ist nicht der richtige Weg, dies zu tun. Stattdessen so geschrieben:

    from c in db.Customers where c.BirthDate >= (maxDate ?? DateTime.MinValue)
    

    ... jetzt weiß die DB-Engine, wie man dies parametrisiert und eine Indexsuche durchführt. Eine geringfügige, scheinbar unbedeutende Änderung des Abfrageausdrucks kann die Leistung drastisch beeinträchtigen.

    Leider macht es LINQ im Allgemeinen allzu einfach, schlechte Abfragen wie diese zu schreiben, weil manchmal die Anbieter erraten können, was Sie versucht haben, und die Abfrage zu optimieren, und manchmal nicht. Sie erhalten also frustrierend inkonsistent Ergebnisse, die (für einen erfahrenen DBA jedenfalls) offensichtlich gewesen wären, wenn Sie nur einfaches altes SQL geschrieben hätten.

    Grundsätzlich kommt es darauf an, dass Sie sowohl das generierte SQL als auch die Ausführungspläne, zu denen sie führen, genau im Auge behalten müssen. Wenn Sie nicht die erwarteten Ergebnisse erzielen, haben Sie keine Angst, das zu umgehen Hin und wieder ORM-Schicht und SQL-Code von Hand. Dies gilt für any ORM, nicht nur für EF.

  6. Transaktionen und Sperren

    Müssen Sie Daten anzeigen, die bis zur Millisekunde aktuell sind? Vielleicht - es kommt darauf an - aber wahrscheinlich nicht. Leider Entity Framework gibt Ihnen nicht nolock , Sie können READ UNCOMMITTED Nur auf der Ebene Transaktion verwenden (nicht auf Tabellenebene ). Tatsächlich ist keines der ORMs diesbezüglich besonders zuverlässig. Wenn Sie Dirty Reads durchführen möchten, müssen Sie auf die SQL-Ebene wechseln und Ad-hoc-Abfragen oder gespeicherte Prozeduren schreiben. Es läuft also wieder darauf hinaus, wie einfach es für Sie ist, dies innerhalb des Rahmens zu tun.

    Entity Framework hat in dieser Hinsicht einen langen Weg zurückgelegt - Version 1 von EF (in .NET 3.5) war schrecklich, machte es unglaublich schwierig, die Abstraktion "Entities" zu durchbrechen, aber jetzt haben Sie ExecuteStoreQuery = und Übersetzen , also ist es wirklich nicht so schlimm. Freunde dich mit diesen Jungs an, weil du sie oft benutzt.

    Es gibt auch das Problem von Schreibsperren und Deadlocks und die allgemeine Praxis, Sperren in der Datenbank so wenig wie möglich zu halten. In dieser Hinsicht sind die meisten ORMs (einschließlich Entity Framework) tatsächlich besser als unformatiertes SQL, da sie das Arbeitseinheit Muster einkapseln, das in EF - SaveChanges . Mit anderen Worten, Sie können Entitäten nach Herzenslust "einfügen" oder "aktualisieren" oder "löschen", wann immer Sie möchten. Dabei können Sie sicher sein, dass keine Änderungen tatsächlich in die Datenbank übertragen werden, bis Sie die Arbeitseinheit festschreiben.

    Beachten Sie, dass ein UOW nicht analog zu einer lang laufenden Transaktion ist. Das UOW verwendet weiterhin die optimistischen Parallelitätsfunktionen des ORM und verfolgt alle Änderungen im Speicher. Bis zum endgültigen Festschreiben wird keine einzige DML-Anweisung ausgegeben. Dies hält die Transaktionszeiten so niedrig wie möglich. Wenn Sie Ihre Anwendung mit Raw SQL erstellen, ist es ziemlich schwierig, dieses verzögerte Verhalten zu erreichen.

    Was dies speziell für EF bedeutet: Machen Sie Ihre Arbeitseinheiten so grob wie möglich und legen Sie sie erst fest, wenn Sie es unbedingt müssen. Wenn Sie dies tun, werden Sie viel weniger Sperrenkonflikte haben als wenn Sie einzelne ADO.NET-Befehle zu zufälligen Zeiten verwenden würden.

Abschließend:

EF ist für Anwendungen mit hohem Datenverkehr und hoher Leistung völlig in Ordnung, genau wie jedes andere Framework für Anwendungen mit hohem Datenverkehr und hoher Leistung. Was zählt, ist, wie Sie es verwenden. Hier ist ein kurzer Vergleich der beliebtesten Frameworks und der Funktionen, die sie in Bezug auf die Leistung bieten (Legende: N = Nicht unterstützt, P = Teilweise, Y = Ja/unterstützt):

                                | L2S | EF1 | EF4 | NH3 | ADO
                                +-----+-----+-----+-----+-----
Lazy Loading (entities)         |  N  |  N  |  N  |  Y  |  N
Lazy Loading (relationships)    |  Y  |  Y  |  Y  |  Y  |  N
Eager Loading (global)          |  N  |  N  |  N  |  Y  |  N
Eager Loading (per-session)     |  Y  |  N  |  N  |  Y  |  N
Eager Loading (per-query)       |  N  |  Y  |  Y  |  Y  |  Y
Level 1 (Identity) Cache        |  Y  |  Y  |  Y  |  Y  |  N
Level 2 (Query) Cache           |  N  |  N  |  P  |  Y  |  N
Compiled Queries                |  Y  |  P  |  Y  |  N  | N/A
Multi-Queries                   |  N  |  N  |  N  |  Y  |  Y
Multiple Result Sets            |  Y  |  N  |  P  |  Y  |  Y
Futures                         |  N  |  N  |  N  |  Y  |  N
Explicit Locking (per-table)    |  N  |  N  |  N  |  P  |  Y
Transaction Isolation Level     |  Y  |  Y  |  Y  |  Y  |  Y
Ad-Hoc Queries                  |  Y  |  P  |  Y  |  Y  |  Y
Stored Procedures               |  Y  |  P  |  Y  |  Y  |  Y
Unit of Work                    |  Y  |  Y  |  Y  |  Y  |  N

Wie Sie sehen können, schneidet EF4 (die aktuelle Version) nicht schlecht ab, aber es ist wahrscheinlich nicht das Beste, wenn die Leistung Ihr Hauptanliegen ist. NHibernate ist in diesem Bereich viel ausgereifter und selbst Linq to SQL bietet einige leistungssteigernde Funktionen, die EF immer noch nicht bietet. Raw ADO.NET ist für sehr spezifisch Datenzugriffsszenarien oft schneller, aber wenn Sie alle Teile zusammenfügen, bietet es wirklich nicht viele wichtige Vorteile, die Sie haben Holen Sie sich aus den verschiedenen Frameworks.

Und nur um sicherzugehen, dass ich wie ein gebrochener Rekord klinge, ist nichts davon im geringsten von Bedeutung, wenn Sie Ihre Datenbank-, Anwendungs- und Datenzugriffsstrategien nicht richtig entwerfen. Alle Elemente in der obigen Tabelle sind für Verbesserung Leistung über die Basislinie hinaus; In den meisten Fällen muss die Basislinie selbst am meisten verbessert werden.

216
Aaronaught

Bearbeiten: Basierend auf der großartigen Antwort von @Aaronaught füge ich einige Punkte hinzu, die auf die Leistung mit EF abzielen. Diesen neuen Punkten wird Bearbeiten vorangestellt.


Die größte Leistungsverbesserung bei Websites mit hohem Datenverkehr wird durch Zwischenspeichern (= zunächst Vermeiden einer Webserververarbeitung oder Datenbankabfrage) und anschließende asynchrone Verarbeitung erzielt, um das Blockieren von Threads während der Datenbankabfragen zu vermeiden.

Es gibt keine kugelsichere Antwort auf Ihre Frage, da dies immer von den Anforderungen für die Anwendung und der Komplexität der Abfragen abhängt. Die Wahrheit ist, dass die Entwicklerproduktivität mit EF die Komplexität verbirgt, was in vielen Fällen zu einer falschen Verwendung von EF und einer schrecklichen Leistung führt. Die Idee, dass Sie eine abstrahierte Schnittstelle auf hoher Ebene für den Datenzugriff verfügbar machen können und diese in allen Fällen reibungslos funktioniert, funktioniert nicht. Selbst mit ORM müssen Sie wissen, was hinter der Abstraktion passiert und wie Sie sie richtig verwenden.

Wenn Sie noch keine Erfahrung mit EF haben, werden Sie beim Umgang mit Leistung auf viele Herausforderungen stoßen. Bei der Arbeit mit EF können Sie im Vergleich zu ADO.NET viel mehr Fehler machen. Außerdem wird in EF viel zusätzliche Verarbeitung durchgeführt, sodass EF immer erheblich langsamer ist als natives ADO.NET - dies können Sie anhand einer einfachen Proof-of-Concept-Anwendung messen.

Wenn Sie die beste Leistung von EF erzielen möchten, müssen Sie höchstwahrscheinlich:

  • Überarbeiten Sie Ihren Datenzugriff mit dem SQL-Profiler sehr sorgfältig und überprüfen Sie Ihre LINQ-Abfragen, wenn sie Linq-to-Entities anstelle von Linq-to-Objects korrekt verwenden
  • Verwenden Sie erweiterte EF-Optimierungsfunktionen wie MergeOption.NoTracking
  • Verwenden Sie in einigen Fällen ESQL
  • Vorkompilieren von Abfragen, die häufig ausgeführt werden
  • Denken Sie daran, den EF Caching-Wrapper zu nutzen, um für einige Abfragen eine Cache-ähnliche Funktion der zweiten Ebene zu erhalten
  • Verwenden Sie in einigen Szenarien SQL-Ansichten oder benutzerdefinierte zugeordnete SQL-Abfragen (erfordert die manuelle Pflege der EDMX-Datei) für häufig verwendete Projektionen oder Aggregationen, für die Leistungsverbesserungen erforderlich sind
  • Verwenden Sie natives SQL und gespeicherte Prozeduren für einige Abfragen, die in Linq oder ESQL keine ausreichende Leistung bieten
  • Bearbeiten: Verwenden Sie Abfragen sorgfältig - jede Abfrage führt einen separaten Roundtrip zur Datenbank durch. EFv4 verfügt über keine Abfrage-Stapelverarbeitung, da nicht mehrere Ergebnismengen pro ausgeführtem Datenbankbefehl verwendet werden können. EFv4.5 unterstützt mehrere Ergebnismengen für zugeordnete gespeicherte Prozeduren.
  • Bearbeiten: Arbeiten Sie sorgfältig mit Datenänderungen. Wieder EF fehlt die Befehlsstapelung vollständig . In ADO.NET können Sie also ein einzelnes SqlCommand verwenden, das mehrere Einfügungen, Aktualisierungen oder Löschungen enthält. Mit EF wird jedoch jeder dieser Befehle in einem separaten Roundtrip zur Datenbank ausgeführt.
  • Bearbeiten: Arbeiten Sie sorgfältig mit Identity Map/Identity Cache. EF verfügt über eine spezielle Methode (GetByKey in der ObjectContext-API oder Find in der DbContext-API), um zuerst den Cache abzufragen. Wenn Sie Linq-to-Entities oder ESQL verwenden, wird ein Roundtrip zur Datenbank erstellt und anschließend die vorhandene Instanz aus dem Cache zurückgegeben.
  • Bearbeiten: Verwenden Sie das eifrige Laden vorsichtig. Es ist nicht immer eine Win-Win-Lösung, da es eine riesiger Datensatz erzeugt. Wie Sie sehen, ist dies eine Menge zusätzlicher Komplexität, und das ist der springende Punkt. ORM vereinfacht das Mapping und die Materialisierung, aber wenn es um Leistung geht, wird es viel komplexer und Sie müssen Kompromisse eingehen.

Ich bin mir nicht sicher, ob SO verwendet immer noch L2S. Sie haben ein neues Open-Source-ORM namens Dapper entwickelt, und ich denke, der Hauptgrund für diese Entwicklung war die Steigerung der Leistung.

38
Ladislav Mrnka