Überlegungen zur Leistung von EF 4, 5 und 6Performance considerations for EF 4, 5, and 6

Von David Obando, Eric erttinger und anderenBy David Obando, Eric Dettinger and others

Veröffentlicht: April 2012Published: April 2012

Letzte Aktualisierung: Mai 2014Last updated: May 2014


1. Einführung1. Introduction

Object-Relational Mapping-Frameworks sind eine bequeme Möglichkeit, eine Abstraktion für den Datenzugriff in einer objektorientierten Anwendung bereitzustellen.Object-Relational Mapping frameworks are a convenient way to provide an abstraction for data access in an object-oriented application. Für .NET-Anwendungen ist der empfohlene O/RM von Microsoft Entity Framework.For .NET applications, Microsoft's recommended O/RM is Entity Framework. Mit jeder Abstraktion kann die Leistung jedoch zu einem Problem werden.With any abstraction though, performance can become a concern.

Dieses Whitepaper wurde geschrieben, um die Leistungs Überlegungen beim Entwickeln von Anwendungen mit Entity Framework zu veranschaulichen, um Entwicklern eine Vorstellung von den Entity Framework internen Algorithmen zu vermitteln, die die Leistung beeinträchtigen können, und um Tipps zur Untersuchung und zur Verbesserung der Leistung in Ihren Anwendungen bereitzustellen, die Entity Framework verwenden.This whitepaper was written to show the performance considerations when developing applications using Entity Framework, to give developers an idea of the Entity Framework internal algorithms that can affect performance, and to provide tips for investigation and improving performance in their applications that use Entity Framework. Es gibt eine Reihe von guten Themen zur Leistung, die bereits im Web verfügbar sind, und wir haben auch versucht, nach Möglichkeit auf diese Ressourcen zu verweisen.There are a number of good topics on performance already available on the web, and we've also tried pointing to these resources where possible.

Die Leistung ist ein kniffliges Thema.Performance is a tricky topic. Dieses Whitepaper ist als Ressource gedacht, mit der Sie Leistungs relevante Entscheidungen für Ihre Anwendungen treffen können, die Entity Framework verwenden.This whitepaper is intended as a resource to help you make performance related decisions for your applications that use Entity Framework. Wir haben einige Testmetriken eingefügt, um die Leistung zu veranschaulichen, aber diese Metriken sind nicht als absolute Indikatoren für die Leistung gedacht, die Sie in Ihrer Anwendung sehen werden.We have included some test metrics to demonstrate performance, but these metrics aren't intended as absolute indicators of the performance you will see in your application.

Aus praktischen Gründen wird in diesem Dokument davon ausgegangen, dass Entity Framework 4 unter .NET 4,0 und Entity Framework 5 und 6 unter .NET 4,5 ausgeführt wird.For practical purposes, this document assumes Entity Framework 4 is run under .NET 4.0 and Entity Framework 5 and 6 are run under .NET 4.5. Viele der Leistungsverbesserungen für Entity Framework 5 befinden sich in den Kernkomponenten, die mit .NET 4,5 ausgeliefert werden.Many of the performance improvements made for Entity Framework 5 reside within the core components that ship with .NET 4.5.

Entity Framework 6 ist ein Out-of-Band-Release und ist nicht von den Entity Framework Komponenten abhängig, die mit .net ausgeliefert werden.Entity Framework 6 is an out of band release and does not depend on the Entity Framework components that ship with .NET. Entity Framework 6 funktioniert sowohl mit .NET 4,0 als auch mit .NET 4,5 und bietet einen großen Leistungsvorteil für diejenigen, die kein Upgrade von .NET 4,0 durchgeführt haben, aber die neuesten Entity Framework Bits in Ihrer Anwendung benötigen.Entity Framework 6 work on both .NET 4.0 and .NET 4.5, and can offer a big performance benefit to those who haven’t upgraded from .NET 4.0 but want the latest Entity Framework bits in their application. Wenn in diesem Dokument Entity Framework 6 erwähnt wird, verweist es auf die neueste Version, die zum Zeitpunkt der Erstellung dieses Artikels verfügbar ist: Version 6.1.0.When this document mentions Entity Framework 6, it refers to the latest version available at the time of this writing: version 6.1.0.

2. kalte und warm-Abfrage Ausführung2. Cold vs. Warm Query Execution

Das erste Mal, wenn eine Abfrage für ein bestimmtes Modell durchgeführt wird, führt die Entity Framework viel Arbeit im Hintergrund aus, um das Modell zu laden und zu überprüfen.The very first time any query is made against a given model, the Entity Framework does a lot of work behind the scenes to load and validate the model. Diese erste Abfrage wird häufig als "kalte" Abfrage bezeichnet.We frequently refer to this first query as a "cold" query.Weitere Abfragen für ein bereits geladenes Modell werden als "warm"-Abfragen bezeichnet und sind viel schneller.  Further queries against an already loaded model are known as "warm" queries, and are much faster.

Betrachten wir einen Überblick über die Zeit, die beim Ausführen einer Abfrage mit Entity Framework aufgewendet wird, und sehen uns an, wo sich die Dinge in Entity Framework 6 verbessern.Let’s take a high-level view of where time is spent when executing a query using Entity Framework, and see where things are improving in Entity Framework 6.

Erste Abfrage Ausführung – kalte AbfrageFirst Query Execution – cold query

Schreiben von Code BenutzernCode User Writes AktionAction Auswirkung der EF4 LeistungEF4 Performance Impact Auswirkung der EF5 LeistungEF5 Performance Impact Auswirkung der EF6 LeistungEF6 Performance Impact
using(var db = new MyContext())
{
Kontext ErstellungContext creation MediumMedium MediumMedium NiedrigLow
var q1 =
from c in db.Customers
where c.Id == id1
select c;
Erstellung von Abfrage AusdrückenQuery expression creation NiedrigLow NiedrigLow NiedrigLow
var c1 = q1.First(); LINQ-Abfrage AusführungLINQ query execution -Das Laden von Metadaten: hoch, aber zwischengespeichert- Metadata loading: High but cached
-Generierung anzeigen: potenziell sehr hoch, aber zwischengespeichert- View generation: Potentially very high but cached
-Parameter Auswertung: Mittel- Parameter evaluation: Medium
-Abfrage Übersetzung: Mittel- Query translation: Medium
-Materializer-Generierung: Mittel, aber zwischengespeichert- Materializer generation: Medium but cached
-Datenbankabfrage Ausführung: potenziell hoch- Database query execution: Potentially high
+ Verbindung. Öffnen+ Connection.Open
+ Command.Executereader+ Command.ExecuteReader
+ DataReader. Read+ DataReader.Read
Objektmaterialisierung: MittelObject materialization: Medium
-Identitätssuche: Mittel- Identity lookup: Medium
-Das Laden von Metadaten: hoch, aber zwischengespeichert- Metadata loading: High but cached
-Generierung anzeigen: potenziell sehr hoch, aber zwischengespeichert- View generation: Potentially very high but cached
-Parameter Auswertung: niedrig- Parameter evaluation: Low
-Abfrage Übersetzung: Mittel, aber zwischengespeichert- Query translation: Medium but cached
-Materializer-Generierung: Mittel, aber zwischengespeichert- Materializer generation: Medium but cached
-Datenbankabfrage Ausführung: potenziell hoch (bessere Abfragen in einigen Situationen)- Database query execution: Potentially high (Better queries in some situations)
+ Verbindung. Öffnen+ Connection.Open
+ Command.Executereader+ Command.ExecuteReader
+ DataReader. Read+ DataReader.Read
Objektmaterialisierung: MittelObject materialization: Medium
-Identitätssuche: Mittel- Identity lookup: Medium
-Das Laden von Metadaten: hoch, aber zwischengespeichert- Metadata loading: High but cached
-Sicht Generierung: Mittel, aber zwischengespeichert- View generation: Medium but cached
-Parameter Auswertung: niedrig- Parameter evaluation: Low
-Abfrage Übersetzung: Mittel, aber zwischengespeichert- Query translation: Medium but cached
-Materializer-Generierung: Mittel, aber zwischengespeichert- Materializer generation: Medium but cached
-Datenbankabfrage Ausführung: potenziell hoch (bessere Abfragen in einigen Situationen)- Database query execution: Potentially high (Better queries in some situations)
+ Verbindung. Öffnen+ Connection.Open
+ Command.Executereader+ Command.ExecuteReader
+ DataReader. Read+ DataReader.Read
Objektmaterialisierung: Mittel (schneller als EF5)Object materialization: Medium (Faster than EF5)
-Identitätssuche: Mittel- Identity lookup: Medium
} Verbindung. SchließenConnection.Close NiedrigLow NiedrigLow NiedrigLow

Zweite Abfrage Ausführung – warm AbfrageSecond Query Execution – warm query

Schreiben von Code BenutzernCode User Writes AktionAction Auswirkung der EF4 LeistungEF4 Performance Impact Auswirkung der EF5 LeistungEF5 Performance Impact Auswirkung der EF6 LeistungEF6 Performance Impact
using(var db = new MyContext())
{
Kontext ErstellungContext creation MediumMedium MediumMedium NiedrigLow
var q1 =
from c in db.Customers
where c.Id == id1
select c;
Erstellung von Abfrage AusdrückenQuery expression creation NiedrigLow NiedrigLow NiedrigLow
var c1 = q1.First(); LINQ-Abfrage AusführungLINQ query execution -Das Suchen nach dem metadatenlade Vorgang : hoch, aber zwischengespeichert- Metadata loading lookup: High but cached Low
-Ansicht Generierungs Suche: potenziell sehr hoch, aber zwischengespeichert- View generation lookup: Potentially very high but cached Low
-Parameter Auswertung: Mittel- Parameter evaluation: Medium
-Abfrage Übersetzungs Suche: Mittel- Query translation lookup: Medium
-Materializer Generierungs Suche: Mittel, aber niedrig zwischengespeichert- Materializer generation lookup: Medium but cached Low
-Datenbankabfrage Ausführung: potenziell hoch- Database query execution: Potentially high
+ Verbindung. Öffnen+ Connection.Open
+ Command.Executereader+ Command.ExecuteReader
+ DataReader. Read+ DataReader.Read
Objektmaterialisierung: MittelObject materialization: Medium
-Identitätssuche: Mittel- Identity lookup: Medium
-Das Suchen nach dem metadatenlade Vorgang : hoch, aber zwischengespeichert- Metadata loading lookup: High but cached Low
-Ansicht Generierungs Suche: potenziell sehr hoch, aber zwischengespeichert- View generation lookup: Potentially very high but cached Low
-Parameter Auswertung: niedrig- Parameter evaluation: Low
-Abfrage Übersetzungs Suche: Mittel, aber niedrig zwischengespeichert- Query translation lookup: Medium but cached Low
-Materializer Generierungs Suche: Mittel, aber niedrig zwischengespeichert- Materializer generation lookup: Medium but cached Low
-Datenbankabfrage Ausführung: potenziell hoch (bessere Abfragen in einigen Situationen)- Database query execution: Potentially high (Better queries in some situations)
+ Verbindung. Öffnen+ Connection.Open
+ Command.Executereader+ Command.ExecuteReader
+ DataReader. Read+ DataReader.Read
Objektmaterialisierung: MittelObject materialization: Medium
-Identitätssuche: Mittel- Identity lookup: Medium
-Das Suchen nach dem metadatenlade Vorgang : hoch, aber zwischengespeichert- Metadata loading lookup: High but cached Low
-Ansicht Generierungs Suche: Mittel, aber niedrig zwischengespeichert- View generation lookup: Medium but cached Low
-Parameter Auswertung: niedrig- Parameter evaluation: Low
-Abfrage Übersetzungs Suche: Mittel, aber niedrig zwischengespeichert- Query translation lookup: Medium but cached Low
-Materializer Generierungs Suche: Mittel, aber niedrig zwischengespeichert- Materializer generation lookup: Medium but cached Low
-Datenbankabfrage Ausführung: potenziell hoch (bessere Abfragen in einigen Situationen)- Database query execution: Potentially high (Better queries in some situations)
+ Verbindung. Öffnen+ Connection.Open
+ Command.Executereader+ Command.ExecuteReader
+ DataReader. Read+ DataReader.Read
Objektmaterialisierung: Mittel (schneller als EF5)Object materialization: Medium (Faster than EF5)
-Identitätssuche: Mittel- Identity lookup: Medium
} Verbindung. SchließenConnection.Close NiedrigLow NiedrigLow NiedrigLow

Es gibt mehrere Möglichkeiten, die Leistungskosten sowohl für kalte als auch für warme Abfragen zu reduzieren. im folgenden Abschnitt sehen wir uns diese Informationen an.There are several ways to reduce the performance cost of both cold and warm queries, and we'll take a look at these in the following section. Insbesondere wird die Reduzierung der Kosten für das Laden von Modellen in kalten Abfragen mithilfe von vorab generierten Sichten untersucht, die bei der Generierung von Leistungsproblemen helfen sollen.Specifically, we'll look at reducing the cost of model loading in cold queries by using pre-generated views, which should help alleviate performance pains experienced during view generation. Bei warmen Abfragen werden das Zwischenspeichern von Abfrage Plänen, keine nach Verfolgungs Abfragen und andere Optionen für die Abfrage Ausführung behandelt.For warm queries, we'll cover query plan caching, no tracking queries, and different query execution options.

2,1 Was ist die Ansichts Generierung?2.1 What is View Generation?

Um zu verstehen, welche Sicht Generierung ist, müssen wir zuerst verstehen, was "Mapping views" ist.In order to understand what view generation is, we must first understand what “Mapping Views” are. Zuordnungs Sichten sind ausführbare Darstellungen der in der Zuordnung für jede Entitätenmenge und Zuordnung angegebenen Transformationen.Mapping Views are executable representations of the transformations specified in the mapping for each entity set and association. Intern haben diese Mapping-Sichten die Form von cqts (kanonische Abfrage Strukturen).Internally, these mapping views take the shape of CQTs (canonical query trees). Es gibt zwei Typen von Karten Sichten:There are two types of mapping views:

  • Abfrage Sichten: Diese stellen die Transformation dar, die erforderlich ist, um vom Datenbankschema zum konzeptionellen Modell zu wechseln.Query views: these represent the transformation necessary to go from the database schema to the conceptual model.
  • Aktualisieren von Sichten: Diese stellen die Transformation dar, die erforderlich ist, um vom konzeptionellen Modell zum Datenbankschema zu wechseln.Update views: these represent the transformation necessary to go from the conceptual model to the database schema.

Beachten Sie, dass das konzeptionelle Modell auf unterschiedliche Weise vom Datenbankschema abweichen kann.Keep in mind that the conceptual model might differ from the database schema in various ways. Beispielsweise kann eine einzelne Tabelle zum Speichern der Daten für zwei verschiedene Entitäts Typen verwendet werden.For example, one single table might be used to store the data for two different entity types. Vererbung und nicht triviale Zuordnungen spielen bei der Komplexität der Zuordnungs Sichten eine Rolle.Inheritance and non-trivial mappings play a role in the complexity of the mapping views.

Das Berechnen dieser Sichten auf der Grundlage der Spezifikation der Zuordnung ist das, was wir als Ansichts Generierung bezeichnen.The process of computing these views based on the specification of the mapping is what we call view generation. Die Ansichts Generierung kann entweder dynamisch erfolgen, wenn ein Modell geladen wird, oder zur Buildzeit mithilfe von "vorgenerierten Sichten"; Letztere werden in Form von Entity SQL-Anweisungen in eine C- # oder VB-Datei serialisiert.View generation can either take place dynamically when a model is loaded, or at build time, by using "pre-generated views"; the latter are serialized in the form of Entity SQL statements to a C# or VB file.

Wenn Sichten generiert werden, werden Sie ebenfalls überprüft.When views are generated, they are also validated. Aus Sicht der Leistung ist der Großteil der Kosten der Ansichts Generierung tatsächlich die Validierung der Sichten, die sicherstellt, dass die Verbindungen zwischen den Entitäten sinnvoll sind und über die richtige Kardinalität für alle unterstützten Vorgänge verfügen.From a performance standpoint, the vast majority of the cost of view generation is actually the validation of the views which ensures that the connections between the entities make sense and have the correct cardinality for all the supported operations.

Wenn eine Abfrage über eine Entitätenmenge ausgeführt wird, wird die Abfrage mit der entsprechenden Abfrage Ansicht kombiniert, und das Ergebnis dieser Komposition wird durch den Plan Compiler ausgeführt, um die Darstellung der Abfrage zu erstellen, die der Sicherungs Speicher verstehen kann.When a query over an entity set is executed, the query is combined with the corresponding query view, and the result of this composition is run through the plan compiler to create the representation of the query that the backing store can understand. Bei SQL Server ist das Endergebnis dieser Kompilierung eine T-SQL-SELECT-Anweisung.For SQL Server, the final result of this compilation will be a T-SQL SELECT statement. Wenn ein Update für eine Entitätenmenge zum ersten Mal ausgeführt wird, wird die Update Ansicht durch einen ähnlichen Prozess ausgeführt, um Sie in DML-Anweisungen für die Zieldatenbank umzuwandeln.The first time an update over an entity set is performed, the update view is run through a similar process to transform it into DML statements for the target database.

2,2 Faktoren, die die Leistung der Ansichts Generierung beeinflussen2.2 Factors that affect View Generation performance

Die Leistung des Ansichts Generierungs Schritts hängt nicht nur von der Größe des Modells, sondern auch davon ab, wie das Modell miteinander verbunden ist.The performance of view generation step not only depends on the size of your model but also on how interconnected the model is. Wenn zwei Entitäten über eine Vererbungs Kette oder eine Zuordnung verbunden sind, werden Sie als verbunden bezeichnet.If two Entities are connected via an inheritance chain or an Association, they are said to be connected. Wenn zwei Tabellen über einen Fremdschlüssel verbunden sind, sind Sie ebenfalls verbunden.Similarly if two tables are connected via a foreign key, they are connected. Wenn die Anzahl der verbundenen Entitäten und Tabellen in den Schemas zunimmt, steigt die Kosten der Ansichts Generierung.As the number of connected Entities and tables in your schemas increase, the view generation cost increases.

Der Algorithmus, der zum Generieren und Validieren von Sichten verwendet wird, ist im schlimmsten Fall exponentiell, obwohl wir einige Optimierungen verwenden, um dies zu verbessern.The algorithm that we use to generate and validate views is exponential in the worst case, though we do use some optimizations to improve this. Die wichtigsten Faktoren, die sich negativ auf die Leistung auswirken, sind folgende:The biggest factors that seem to negatively affect performance are:

  • Modell Größe, die auf die Anzahl der Entitäten und die Menge der Zuordnungen zwischen diesen Entitäten verweist.Model size, referring to the number of entities and the amount of associations between these entities.
  • Modell Komplexität, insbesondere Vererbung für eine große Anzahl von Typen.Model complexity, specifically inheritance involving a large number of types.
  • Verwenden unabhängiger Zuordnungen anstelle von Fremdschlüssel Zuordnungen.Using Independent Associations, instead of Foreign Key Associations.

Für kleine, einfache Modelle können die Kosten klein genug sein, um sich nicht mit vorgenerierten Sichten zu beschäftigen.For small, simple models the cost may be small enough to not bother using pre-generated views. Wenn die Modell Größe und-Komplexität zunehmen, stehen mehrere Optionen zur Verfügung, um die Kosten für die Anzeige Generierung und-Überprüfung zu verringern.As model size and complexity increase, there are several options available to reduce the cost of view generation and validation.

2,3 Verwenden von vordefinierten Sichten zum Verringern der Ladezeit des Modells2.3 Using Pre-Generated Views to decrease model load time

Ausführliche Informationen zur Verwendung von vordefinierten Sichten auf Entity Framework 6 finden Sie unter vorgenerierte Mapping-Sichten .For detailed information on how to use pre-generated views on Entity Framework 6 visit Pre-Generated Mapping Views

2.3.1 vorgenerierte Ansichten mit der Entity Framework Power Tools Community Edition2.3.1 Pre-Generated views using the Entity Framework Power Tools Community Edition

Mit der Entity Framework 6 Power Tools Community Edition können Sie Ansichten von edmx-und Code First Modellen generieren, indem Sie mit der rechten Maustaste auf die Modellklassen Datei klicken und das Menü Entity Framework verwenden, um "Sichten generieren" auszuwählen.You can use the Entity Framework 6 Power Tools Community Edition to generate views of EDMX and Code First models by right-clicking the model class file and using the Entity Framework menu to select “Generate Views”. Die Entity Framework Power Tools Community Edition funktioniert nur in Zusammenhang mit dbcontext-abgeleiteten Kontexten.The Entity Framework Power Tools Community Edition work only on DbContext-derived contexts.

2.3.2 verwenden vorgenerierter Sichten mit einem von EdmGen erstellten Modell2.3.2 How to use Pre-generated views with a model created by EDMGen

EdmGen ist ein Hilfsprogramm, das mit .net ausgeliefert wird und mit Entity Framework 4 und 5, aber nicht mit Entity Framework 6 funktioniert.EDMGen is a utility that ships with .NET and works with Entity Framework 4 and 5, but not with Entity Framework 6. Mit EdmGen können Sie eine Modelldatei, die Objektebene und die Ansichten von der Befehlszeile aus generieren.EDMGen allows you to generate a model file, the object layer and the views from the command line. Bei einer der Ausgaben handelt es sich um eine Ansichts Datei in Ihrer bevorzugten Sprache, VB oder C # .One of the outputs will be a Views file in your language of choice, VB or C#. Dies ist eine Codedatei, die Entity SQL Ausschnitte für jede Entitätenmenge enthält.This is a code file containing Entity SQL snippets for each entity set. Um vorab generierte Sichten zu aktivieren, schließen Sie einfach die Datei in Ihr Projekt ein.To enable pre-generated views, you simply include the file in your project.

Wenn Sie Änderungen an den Schema Dateien für das Modell manuell vornehmen, müssen Sie die Ansichts Datei erneut generieren.If you manually make edits to the schema files for the model, you will need to re-generate the views file. Hierfür können Sie EdmGen mit dem Flag /Mode: viewgene Ration ausführen.You can do this by running EDMGen with the /mode:ViewGeneration flag.

2.3.3 verwenden vorgenerierter Sichten mit einer EDMX-Datei2.3.3 How to use Pre-Generated Views with an EDMX file

Sie können EdmGen auch zum Generieren von Sichten für eine EDMX-Datei verwenden. im zuvor referenzierten MSDN-Thema wird beschrieben, wie Sie hierfür ein Präbuildereignis hinzufügen können. Dies ist jedoch kompliziert, und es gibt einige Fälle, in denen es nicht möglich ist.You can also use EDMGen to generate views for an EDMX file - the previously referenced MSDN topic describes how to add a pre-build event to do this - but this is complicated and there are some cases where it isn't possible. Im Allgemeinen ist es einfacher, eine T4-Vorlage zu verwenden, um die Sichten zu generieren, wenn das Modell in einer EDMX-Datei ist.It's generally easier to use a T4 template to generate the views when your model is in an edmx file.

Der ADO.NET-Teamblog enthält einen Beitrag, der beschreibt, wie eine T4-Vorlage für die Ansichts Generierung () verwendet wird <https://docs.microsoft.com/archive/blogs/adonet/how-to-use-a-t4-template-for-view-generation> .The ADO.NET team blog has a post that describes how to use a T4 template for view generation ( <https://docs.microsoft.com/archive/blogs/adonet/how-to-use-a-t4-template-for-view-generation>). Dieser Beitrag enthält eine Vorlage, die heruntergeladen und dem Projekt hinzugefügt werden kann.This post includes a template that can be downloaded and added to your project. Die Vorlage wurde für die erste Version von Entity Framework geschrieben, sodass Sie mit den neuesten Versionen von Entity Framework nicht sicher funktionieren.The template was written for the first version of Entity Framework, so they aren’t guaranteed to work with the latest versions of Entity Framework. Sie können jedoch einen aktuellere Satz von Ansichts Generierungs Vorlagen für Entity Framework 4 und 5 aus der Visual Studio Gallery herunterladen:However, you can download a more up-to-date set of view generation templates for Entity Framework 4 and 5from the Visual Studio Gallery:

  • VB.net: <http://visualstudiogallery.msdn.microsoft.com/118b44f2-1b91-4de2-a584-7a680418941d>VB.NET: <http://visualstudiogallery.msdn.microsoft.com/118b44f2-1b91-4de2-a584-7a680418941d>
  • C # : <http://visualstudiogallery.msdn.microsoft.com/ae7730ce-ddab-470f-8456-1b313cd2c44d>C#: <http://visualstudiogallery.msdn.microsoft.com/ae7730ce-ddab-470f-8456-1b313cd2c44d>

Wenn Sie Entity Framework 6 verwenden, können Sie die T4-Vorlagen der Sicht Generierung aus der Visual Studio Gallery unter erhalten <http://visualstudiogallery.msdn.microsoft.com/18a7db90-6705-4d19-9dd1-0a6c23d0751f> .If you’re using Entity Framework 6 you can get the view generation T4 templates from the Visual Studio Gallery at <http://visualstudiogallery.msdn.microsoft.com/18a7db90-6705-4d19-9dd1-0a6c23d0751f>.

2,4 verringern der Kosten für die Ansichts Generierung2.4 Reducing the cost of view generation

Durch die Verwendung von vorgenerierten Sichten werden die Kosten der Ansichts Generierung von der Modell Lade Zeit (Laufzeit) zur Entwurfszeit verschoben.Using pre-generated views moves the cost of view generation from model loading (run time) to design time. Obwohl dies die Startleistung zur Laufzeit verbessert, treten die Probleme bei der Ansichts Generierung während der Entwicklung immer noch auf.While this improves startup performance at runtime, you will still experience the pain of view generation while you are developing. Es gibt mehrere zusätzliche Tricks, die dazu beitragen können, die Kosten der Ansichts Generierung zu reduzieren, sowohl zur Kompilierzeit als auch zur Laufzeit.There are several additional tricks that can help reduce the cost of view generation, both at compile time and run time.

2.4.1 mit Fremdschlüssel Zuordnungen zum Reduzieren der Ansichts Generierungs Kosten2.4.1 Using Foreign Key Associations to reduce view generation cost

Wir haben eine Reihe von Fällen gesehen, in denen das Wechseln der Zuordnungen im Modell von unabhängigen Zuordnungen zu Fremdschlüssel Zuordnungen die für die Sicht Generierung aufgewendeten Zeit erheblich verbessert hat.We have seen a number of cases where switching the associations in the model from Independent Associations to Foreign Key Associations dramatically improved the time spent in view generation.

Um diese Verbesserung zu veranschaulichen, haben wir mithilfe von EdmGen zwei Versionen des Navision-Modells generiert.To demonstrate this improvement, we generated two versions of the Navision model by using EDMGen. Hinweis: eine Beschreibung des Navision-Modells finden Sie in Anhang C.Note: see appendix C for a description of the Navision model. Das Navision-Modell ist für diese Übung interessant, weil es eine große Menge an Entitäten und Beziehungen zwischen Ihnen gibt.The Navision model is interesting for this exercise due to its very large amount of entities and relationships between them.

Eine Version dieses sehr großen Modells wurde mit Fremdschlüssel Zuordnungen generiert, und die andere Version wurde mit unabhängigen Zuordnungen generiert.One version of this very large model was generated with Foreign Keys Associations and the other was generated with Independent Associations. Dann haben wir festgenommen, wie lange es gedauert hat, die Ansichten für jedes Modell zu generieren.We then timed how long it took to generate the views for each model. Entity Framework 5-Test verwendete die GenerateViews ()-Methode aus der EntityViewGenerator-Klasse, um die Sichten zu generieren, während der Entity Framework 6-Test die GenerateViews ()-Methode aus der StorageMappingItemCollection-Klasse verwendete.Entity Framework 5 test used the GenerateViews() method from class EntityViewGenerator to generate the views, while the Entity Framework 6 test used the GenerateViews() method from class StorageMappingItemCollection. Dies ist auf die Code Umstrukturierung zurückzuführen, die in der-CodeBase Entity Framework 6 aufgetreten ist.This due to code restructuring that occurred in the Entity Framework 6 codebase.

Bei Verwendung von Entity Framework 5 benötigte die Anzeige Generierung für das Modell mit Fremdschlüsseln 65 Minuten in einem Lab-Computer.Using Entity Framework 5, view generation for the model with Foreign Keys took 65 minutes in a lab machine. Es ist unbekannt, wie lange es gedauert hätte, die Ansichten für das Modell zu generieren, die unabhängige Zuordnungen verwendet haben.It's unknown how long it would have taken to generate the views for the model that used independent associations. Wir haben den Test über einen Monat lang ausgeführt, bevor der Computer in unserem Lab neu gestartet wurde, um monatliche Updates zu installieren.We left the test running for over a month before the machine was rebooted in our lab to install monthly updates.

Bei Verwendung von Entity Framework 6 benötigte die Anzeige Generierung für das Modell mit Fremdschlüsseln 28 Sekunden im gleichen Lab-Computer.Using Entity Framework 6, view generation for the model with Foreign Keys took 28 seconds in the same lab machine. Die Ansichts Generierung für das Modell, das unabhängige Zuordnungen verwendet, hat 58 Sekunden gedauert.View generation for the model that uses Independent Associations took 58 seconds. Durch die Verbesserungen an Entity Framework 6 auf dem Code der Ansichts Generierung bedeutet dies, dass viele Projekte keine vorab generierten Sichten benötigen, um schnellere Startzeiten zu erzielen.The improvements done to Entity Framework 6 on its view generation code mean that many projects won’t need pre-generated views to obtain faster startup times.

Es ist wichtig zu beachten, dass die vorab Generierung von Sichten in Entity Framework 4 und 5 mit EdmGen oder den Entity Framework Power Tools erfolgen kann.It’s important to remark that pre-generating views in Entity Framework 4 and 5 can be done with EDMGen or the Entity Framework Power Tools. Entity Framework 6-Sicht Generierung kann über die Entity Framework Power Tools oder Programm gesteuert durchgeführt werden, wie in vorab generierten Zustellungs Sichtenbeschrieben.For Entity Framework 6 view generation can be done via the Entity Framework Power Tools or programmatically as described in Pre-Generated Mapping Views.

2.4.1.1 Verwenden von Fremdschlüsseln anstelle unabhängiger Zuordnungen2.4.1.1 How to use Foreign Keys instead of Independent Associations

Wenn Sie EdmGen oder das Entity Designer in Visual Studio verwenden, erhalten Sie standardmäßig Fert, und es wird nur ein Kontrollkästchen oder ein befehlszeilenflag zum Wechseln zwischen den fschen und IAS benötigt.When using EDMGen or the Entity Designer in Visual Studio, you get FKs by default, and it only takes a single checkbox or command line flag to switch between FKs and IAs.

Wenn Sie über ein großes Code First Modell verfügen, hat die Verwendung unabhängiger Zuordnungen dieselbe Auswirkung auf die Ansichts Generierung.If you have a large Code First model, using Independent Associations will have the same effect on view generation. Sie können diese Auswirkung vermeiden, indem Sie Fremdschlüssel Eigenschaften in die Klassen für die abhängigen Objekte einschließen. einige Entwickler werden dies jedoch in Erwägung gezogen, um Ihr Objektmodell zu beschädigen.You can avoid this impact by including Foreign Key properties on the classes for your dependent objects, though some developers will consider this to be polluting their object model. Weitere Informationen zu diesem Betreff finden Sie unter <http://blog.oneunicorn.com/2011/12/11/whats-the-deal-with-mapping-foreign-keys-using-the-entity-framework/> .You can find more information on this subject in <http://blog.oneunicorn.com/2011/12/11/whats-the-deal-with-mapping-foreign-keys-using-the-entity-framework/>.

Bei Verwendung vonWhen using AktionDo this
Entity DesignerEntity Designer Stellen Sie nach dem Hinzufügen einer Zuordnung zwischen zwei Entitäten sicher, dass Sie über eine referenzielle Einschränkung verfügen.After adding an association between two entities, make sure you have a referential constraint. Referenzielle Einschränkungen Teilen Entity Framework die Verwendung von Fremdschlüsseln anstelle unabhängiger Zuordnungen.Referential constraints tell Entity Framework to use Foreign Keys instead of Independent Associations. Weitere Informationen finden Sie unter <https://docs.microsoft.com/archive/blogs/efdesign/foreign-keys-in-the-entity-framework> .For additional details visit <https://docs.microsoft.com/archive/blogs/efdesign/foreign-keys-in-the-entity-framework>.
EDMGenEDMGen Wenn Sie die Dateien mithilfe von EdmGen aus der Datenbank generieren, werden die Fremdschlüssel berücksichtigt und dem Modell als solche hinzugefügt.When using EDMGen to generate your files from the database, your Foreign Keys will be respected and added to the model as such. Weitere Informationen zu den verschiedenen Optionen, die von EdmGen angeboten werden, finden Sie unter http://msdn.microsoft.com/library/bb387165.aspx .For more information on the different options exposed by EDMGen visit http://msdn.microsoft.com/library/bb387165.aspx.
Code FirstCode First Weitere Informationen zum Einschließen von Fremdschlüssel Eigenschaften für abhängige Objekte bei Verwendung von Code First finden Sie im Abschnitt "Beziehungs Konvention" im Thema Code First Konventionen .See the "Relationship Convention" section of the Code First Conventions topic for information on how to include foreign key properties on dependent objects when using Code First.

2.4.2 Verschieben des Modells in eine separate Assembly2.4.2 Moving your model to a separate assembly

Wenn Ihr Modell direkt in das Projekt Ihrer Anwendung eingefügt wird und Sie Sichten über ein Präbuildereignis oder eine T4-Vorlage generieren, werden die Ansichts Generierung und-Validierung immer dann durchgeführt, wenn das Projekt neu erstellt wird, auch wenn das Modell nicht geändert wurde.When your model is included directly in your application's project and you generate views through a pre-build event or a T4 template, view generation and validation will take place whenever the project is rebuilt, even if the model wasn't changed. Wenn Sie das Modell in eine separate Assembly verschieben und aus dem Projekt Ihrer Anwendung darauf verweisen, können Sie andere Änderungen an Ihrer Anwendung vornehmen, ohne das Projekt neu erstellen zu müssen, das das Modell enthält.If you move the model to a separate assembly and reference it from your application's project, you can make other changes to your application without needing to rebuild the project containing the model.

Hinweis:   Wenn Sie das Modell in separate Assemblys verschieben, denken Sie daran, die Verbindungs Zeichenfolgen für das Modell in die Anwendungs Konfigurationsdatei des Client Projekts zu kopieren.Note:  when moving your model to separate assemblies remember to copy the connection strings for the model into the application configuration file of the client project.

2.4.3 Deaktivieren der Überprüfung eines edmx-basierten Modells2.4.3 Disable validation of an edmx-based model

Edmx-Modelle werden zur Kompilierzeit überprüft, auch wenn das Modell unverändert ist.EDMX models are validated at compile time, even if the model is unchanged. Wenn das Modell bereits überprüft wurde, können Sie die Überprüfung zur Kompilierzeit unterdrücken, indem Sie im Eigenschaften Fenster die Eigenschaft "auf Build überprüfen" auf "false" festlegen.If your model has already been validated, you can suppress validation at compile time by setting the "Validate on Build" property to false in the properties window. Wenn Sie die Zuordnung oder das Modell ändern, können Sie die Überprüfung vorübergehend erneut aktivieren, um die Änderungen zu überprüfen.When you change your mapping or model, you can temporarily re-enable validation to verify your changes.

Beachten Sie, dass die Entity Framework Designer für Entity Framework 6 Leistungsverbesserungen vorgenommen wurden und die Kosten für "überprüfen bei Build" wesentlich niedriger sind als in früheren Versionen des Designers.Note that performance improvements were made to the Entity Framework Designer for Entity Framework 6, and the cost of the “Validate on Build” is much lower than in previous versions of the designer.

3 Caching in der Entity Framework3 Caching in the Entity Framework

In Entity Framework sind die folgenden Formen der Zwischenspeicherung integriert:Entity Framework has the following forms of caching built-in:

  1. Objekt Zwischenspeicherung – der in eine ObjectContext-Instanz integrierte objectstatus Manager behält den Arbeitsspeicher der Objekte bei, die mit dieser Instanz abgerufen wurden.Object caching – the ObjectStateManager built into an ObjectContext instance keeps track in memory of the objects that have been retrieved using that instance. Dies wird auch als Cache der ersten Ebene bezeichnet.This is also known as first-level cache.
  2. Zwischenspeichern von Abfrage Plänen: wieder verwenden des generierten Speicher Befehls, wenn eine Abfrage mehrmals ausgeführt wird.Query Plan Caching - reusing the generated store command when a query is executed more than once.
  3. Metadatencaching: Freigeben der Metadaten für ein Modell über verschiedene Verbindungen zum gleichen Modell.Metadata caching - sharing the metadata for a model across different connections to the same model.

Neben den von EF standardmäßig bereitgestellten Caches kann eine besondere Art von ADO.NET-Datenanbieter, der als Wrapping Anbieter bezeichnet wird, auch verwendet werden, um Entity Framework mit einem Cache für die Ergebnisse zu erweitern, die aus der Datenbank abgerufen werden, auch als Caching der zweiten Ebene bezeichnet.Besides the caches that EF provides out of the box, a special kind of ADO.NET data provider known as a wrapping provider can also be used to extend Entity Framework with a cache for the results retrieved from the database, also known as second-level caching.

3,1 Zwischenspeichern von Objekten3.1 Object Caching

Wenn eine Entität in den Ergebnissen einer Abfrage zurückgegeben wird, kurz bevor EF Sie materialisiert, prüft der ObjectContext standardmäßig, ob eine Entität mit demselben Schlüssel bereits in den objectstatus Ager geladen wurde.By default when an entity is returned in the results of a query, just before EF materializes it, the ObjectContext will check if an entity with the same key has already been loaded into its ObjectStateManager. Wenn bereits eine Entität mit denselben Schlüsseln vorhanden ist, wird Sie von EF in die Ergebnisse der Abfrage eingeschlossen.If an entity with the same keys is already present EF will include it in the results of the query. Obwohl EF immer noch die Abfrage für die Datenbank ausgibt, kann dieses Verhalten einen Großteil der Kosten für eine mehrfache Materialisierung der Entität umgehen.Although EF will still issue the query against the database, this behavior can bypass much of the cost of materializing the entity multiple times.

3.1.1 Abrufen von Entitäten aus dem Objekt Cache mithilfe von dbcontext Find3.1.1 Getting entities from the object cache using DbContext Find

Anders als bei einer regulären Abfrage führt die Find-Methode in dbset (APIs, die zum ersten Mal in EF 4,1 enthalten sind) eine Suche im Speicher aus, bevor Sie die Abfrage für die Datenbank ausgibt.Unlike a regular query, the Find method in DbSet (APIs included for the first time in EF 4.1) will perform a search in memory before even issuing the query against the database. Es ist wichtig zu beachten, dass zwei unterschiedliche ObjectContext-Instanzen zwei unterschiedliche objectstatus Manager-Instanzen aufweisen, was bedeutet, dass Sie über separate Objekt Caches verfügen.It’s important to note that two different ObjectContext instances will have two different ObjectStateManager instances, meaning that they have separate object caches.

Find verwendet den Primärschlüssel Wert, um eine Entität zu suchen, die vom Kontext nachverfolgt wird.Find uses the primary key value to attempt to find an entity tracked by the context. Wenn sich die Entität nicht im Kontext befindet, wird eine Abfrage ausgeführt und mit der Datenbank ausgewertet, und NULL wird zurückgegeben, wenn die Entität nicht im Kontext oder in der Datenbank gefunden wurde.If the entity is not in the context then a query will be executed and evaluated against the database, and null is returned if the entity is not found in the context or in the database. Beachten Sie, dass Find auch Entitäten zurückgibt, die dem Kontext hinzugefügt wurden, aber noch nicht in der Datenbank gespeichert wurden.Note that Find also returns entities that have been added to the context but have not yet been saved to the database.

Bei der Verwendung von Find wird eine Leistungs Überlegung berücksichtigt.There is a performance consideration to be taken when using Find. Bei Aufrufen dieser Methode wird standardmäßig eine Überprüfung des Objekt Caches durchführt, um Änderungen zu erkennen, für die noch ein Commit in der Datenbank aussteht.Invocations to this method by default will trigger a validation of the object cache in order to detect changes that are still pending commit to the database. Dieser Prozess kann sehr kostspielig sein, wenn eine große Anzahl von Objekten im Objekt Cache oder in einem großen Objekt Diagramm dem Objekt Cache hinzugefügt wird. es kann jedoch auch deaktiviert werden.This process can be very expensive if there are a very large number of objects in the object cache or in a large object graph being added to the object cache, but it can also be disabled. In bestimmten Fällen können Sie sich über eine Größenordnung von Unterschieden beim Aufrufen der Find-Methode mit dem Deaktivieren von Änderungen bei der automatischen Erkennung informieren.In certain cases, you may perceive over an order of magnitude of difference in calling the Find method when you disable auto detect changes. Eine zweite Größenordnung wird jedoch wahrgenommen, wenn sich das Objekt tatsächlich im Cache befindet, und wenn das Objekt aus der Datenbank abgerufen werden muss.Yet a second order of magnitude is perceived when the object actually is in the cache versus when the object has to be retrieved from the database. Hier sehen Sie ein Beispiel Diagramm mit Messungen, die mithilfe einiger unserer Mikro Benchmarks (in Millisekunden ausgedrückt) mit einer Auslastung von 5000 Entitäten durchgeführt wurden:Here is an example graph with measurements taken using some of our microbenchmarks, expressed in milliseconds, with a load of 5000 entities:

Logarithmische Skalierung in .NET 4,5.NET 4.5 logarithmic scale

Beispiel für Suche mit deaktiviertem automatischen Erkennen von Änderungen:Example of Find with auto-detect changes disabled:

    context.Configuration.AutoDetectChangesEnabled = false;
    var product = context.Products.Find(productId);
    context.Configuration.AutoDetectChangesEnabled = true;
    ...

Bei der Verwendung der Find-Methode müssen Sie Folgendes beachten:What you have to consider when using the Find method is:

  1. Wenn sich das Objekt nicht im Cache befindet, werden die Vorteile von Find negiert, aber die Syntax ist noch einfacher als eine Abfrage nach Schlüssel.If the object is not in the cache the benefits of Find are negated, but the syntax is still simpler than a query by key.
  2. Wenn die Option zum automatischen Erkennen von Änderungen aktiviert ist, können die Kosten der Find-Methode je nach Komplexität des Modells und der Menge der Entitäten im Objekt Cache in einer Größenordnung zunehmen.If auto detect changes is enabled the cost of the Find method may increase by one order of magnitude, or even more depending on the complexity of your model and the amount of entities in your object cache.

Beachten Sie außerdem, dass Find nur die Entität zurückgibt, nach der Sie suchen, und die zugehörigen Entitäten nicht automatisch lädt, wenn Sie sich nicht bereits im Objekt Cache befinden.Also, keep in mind that Find only returns the entity you are looking for and it does not automatically loads its associated entities if they are not already in the object cache. Wenn Sie zugehörige Entitäten abrufen müssen, können Sie eine Abfrage nach Schlüssel mit Eager Loading verwenden.If you need to retrieve associated entities, you can use a query by key with eager loading. Weitere Informationen finden Sie unter 8,1 Lazy Load im Vergleich zum unverwollten laden.For more information see 8.1 Lazy Loading vs. Eager Loading.

3.1.2 Leistungsprobleme, wenn der Objekt Cache über viele Entitäten verfügt3.1.2 Performance issues when the object cache has many entities

Der Objekt Cache trägt dazu bei, die allgemeine Reaktionsfähigkeit von Entity Framework zu erhöhen.The object cache helps to increase the overall responsiveness of Entity Framework. Wenn jedoch eine große Menge an Entitäten in den Objekt Cache geladen wird, kann sich dies auf bestimmte Vorgänge wie hinzufügen, entfernen, suchen, Eintrags, SaveChanges usw. auswirken.However, when the object cache has a very large amount of entities loaded it may affect certain operations such as Add, Remove, Find, Entry, SaveChanges and more. Insbesondere Vorgänge, die einen aufrufungserkennungs-aufruder DetectChanges auslöst, werden von sehr großen Objekt Caches negativ beeinflusst.In particular, operations that trigger a call to DetectChanges will be negatively affected by very large object caches. DetectChanges synchronisiert das Objekt Diagramm mit dem Objekt Zustands-Manager, und die Leistung wird direkt durch die Größe des Objekt Diagramms bestimmt.DetectChanges synchronizes the object graph with the object state manager and its performance will determined directly by the size of the object graph. Weitere Informationen zu DetectChanges finden Sie unter nach Verfolgen von Änderungen in poco-Entitäten.For more information about DetectChanges, see Tracking Changes in POCO Entities.

Wenn Sie Entity Framework 6 verwenden, können Entwickler AddRange und RemoveRange direkt in einem dbset aufrufen, anstatt eine Auflistung zu durchlaufen und "Add Once" pro Instanz aufrufen zu müssen.When using Entity Framework 6, developers are able to call AddRange and RemoveRange directly on a DbSet, instead of iterating on a collection and calling Add once per instance. Der Vorteil der Verwendung der Bereichs Methoden besteht darin, dass die Kosten von "DetectChanges" nur einmal für den gesamten entitätensatz gezahlt werden, anstatt einmal pro hinzugefügter Entität.The advantage of using the range methods is that the cost of DetectChanges is only paid once for the entire set of entities as opposed to once per each added entity.

3,2 Zwischenspeichern von Abfrage Plänen3.2 Query Plan Caching

Wenn eine Abfrage zum ersten Mal ausgeführt wird, durchläuft Sie den internen Plan Compiler, um die konzeptionelle Abfrage in den Store-Befehl zu übersetzen (z. b. die T-SQL-Anweisung, die ausgeführt wird, wenn Sie für SQL Server ausgeführt wird).The first time a query is executed, it goes through the internal plan compiler to translate the conceptual query into the store command (for example, the T-SQL which is executed when run against SQL Server).Wenn das Zwischenspeichern von Abfrage Plänen aktiviert ist, wird der Speicher Befehl beim nächsten Ausführen der Abfrage direkt aus dem Abfrageplan Cache für die Ausführung abgerufen, wobei der Plan Compiler umgangen wird.  If query plan caching is enabled, the next time the query is executed the store command is retrieved directly from the query plan cache for execution, bypassing the plan compiler.

Der Abfrageplan Cache wird über ObjectContext-Instanzen innerhalb derselben AppDomain freigegeben.The query plan cache is shared across ObjectContext instances within the same AppDomain. Sie müssen sich nicht auf einer ObjectContext-Instanz befinden, um von der Zwischenspeicherung von Abfrage Plänen zu profitieren.You don't need to hold onto an ObjectContext instance to benefit from query plan caching.

3.2.1 einige Hinweise zum Zwischenspeichern von Abfrage Plänen3.2.1 Some notes about Query Plan Caching

  • Der Abfrageplan Cache wird für alle Abfrage Typen freigegeben: Entity SQL, LINQ to Entities und CompiledQuery-Objekten.The query plan cache is shared for all query types: Entity SQL, LINQ to Entities, and CompiledQuery objects.
  • Standardmäßig ist das Zwischenspeichern von Abfrage Plänen für Entity SQL Abfragen aktiviert, unabhängig davon, ob diese über einen EntityCommand oder durch eine ObjectQuery ausgeführt werden.By default, query plan caching is enabled for Entity SQL queries, whether executed through an EntityCommand or through an ObjectQuery. Sie ist auch standardmäßig für LINQ to Entities Abfragen in Entity Framework unter .NET 4,5 und Entity Framework 6 aktiviert.It is also enabled by default for LINQ to Entities queries in Entity Framework on .NET 4.5, and in Entity Framework 6
    • Das Zwischenspeichern von Abfrage Plänen kann deaktiviert werden, indem die EnablePlanCaching-Eigenschaft (für EntityCommand oder ObjectQuery) auf false festgelegt wird.Query plan caching can be disabled by setting the EnablePlanCaching property (on EntityCommand or ObjectQuery) to false. Beispiel:For example:
                    var query = from customer in context.Customer
                                where customer.CustomerId == id
                                select new
                                {
                                    customer.CustomerId,
                                    customer.Name
                                };
                    ObjectQuery oQuery = query as ObjectQuery;
                    oQuery.EnablePlanCaching = false;
  • Bei parametrisierten Abfragen trifft das Ändern des Parameter Werts weiterhin auf die zwischengespeicherte Abfrage.For parameterized queries, changing the parameter's value will still hit the cached query. Beim Ändern der Facetten eines Parameters (z. b. Größe, Genauigkeit oder Skala) wird jedoch ein anderer Eintrag im Cache angezeigt.But changing a parameter's facets (for example, size, precision, or scale) will hit a different entry in the cache.
  • Wenn Sie Entity SQL verwenden, ist die Abfrage Zeichenfolge Teil des Schlüssels.When using Entity SQL, the query string is part of the key. Wenn Sie die Abfrage überhaupt ändern, führt dies zu unterschiedlichen Cache Einträgen, auch wenn die Abfragen funktionell gleichwertig sind.Changing the query at all will result in different cache entries, even if the queries are functionally equivalent. Dies schließt Änderungen an der Groß-/Kleinschreibung oder Leerräume ein.This includes changes to casing or whitespace.
  • Wenn Sie LINQ verwenden, wird die Abfrage verarbeitet, um einen Teil des Schlüssels zu generieren.When using LINQ, the query is processed to generate a part of the key. Wenn Sie den LINQ-Ausdruck ändern, wird daher ein anderer Schlüssel generiert.Changing the LINQ expression will therefore generate a different key.
  • Es können weitere technische Einschränkungen gelten. Weitere Informationen finden Sie unter automatisch kompilierte Abfragen.Other technical limitations may apply; see Autocompiled Queries for more details.

3.2.2 Cache Entfernungs Algorithmus3.2.2      Cache eviction algorithm

Wenn Sie verstehen, wie der interne Algorithmus funktioniert, können Sie herausfinden, wann Sie das Zwischenspeichern von Abfrage Plänen aktivieren oder deaktivieren.Understanding how the internal algorithm works will help you figure out when to enable or disable query plan caching. Der Bereinigungs Algorithmus lautet wie folgt:The cleanup algorithm is as follows:

  1. Wenn der Cache eine festgelegte Anzahl von Einträgen (800) enthält, wird ein Timer gestartet, der in regelmäßigen Abständen (einmal pro Minute) den Cache durch geht.Once the cache contains a set number of entries (800), we start a timer that periodically (once-per-minute) sweeps the cache.
  2. Während des Cache Vorgangs werden Einträge aus dem Cache auf einem lfru-Basis (am wenigsten häufig – zuletzt verwendet) entfernt.During cache sweeps, entries are removed from the cache on a LFRU (Least frequently – recently used) basis. Bei diesem Algorithmus wird sowohl die Treffer Anzahl als auch das Alter berücksichtigt, wenn Sie entscheiden, welche Einträge ausworfen werden.This algorithm takes both hit count and age into account when deciding which entries are ejected.
  3. Am Ende jedes Cache-Sweep enthält der Cache wieder 800 Einträge.At the end of each cache sweep, the cache again contains 800 entries.

Alle Cache Einträge werden gleichermaßen behandelt, wenn bestimmt wird, welche Einträge entfernt werden sollen.All cache entries are treated equally when determining which entries to evict. Dies bedeutet, dass der Speicher Befehl für eine CompiledQuery die gleiche Möglichkeit hat, wie der Speicher Befehl für eine Entity SQL Abfrage zu entfernen.This means the store command for a CompiledQuery has the same chance of eviction as the store command for an Entity SQL query.

Beachten Sie, dass der Cache Entfernungs Zeit Geber in gestartet wird, wenn 800 Entitäten im Cache vorhanden sind. der Cache wird jedoch nur 60 Sekunden nach dem Start dieses Timers überschwemmt.Note that the cache eviction timer is kicked in when there are 800 entities in the cache, but the cache is only swept 60 seconds after this timer is started. Dies bedeutet, dass es bis zu 60 Sekunden dauern kann, bis der Cache sehr groß ist.That means that for up to 60 seconds your cache may grow to be quite large.

3.2.3 Testmetriken veranschaulichen der Zwischenspeicherung von Abfrage Plänen3.2.3       Test Metrics demonstrating query plan caching performance

Um die Auswirkung der Zwischenspeicherung von Abfrage Plänen auf die Leistung Ihrer Anwendung zu veranschaulichen, haben wir einen Test durchgeführt, bei dem wir eine Reihe von Entity SQL Abfragen für das Navision-Modell ausgeführt haben.To demonstrate the effect of query plan caching on your application's performance, we performed a test where we executed a number of Entity SQL queries against the Navision model. Eine Beschreibung des Navision-Modells und der ausgeführten Abfrage Typen finden Sie im Anhang.See the appendix for a description of the Navision model and the types of queries which were executed. In diesem Test durchlaufen wir zuerst die Liste der Abfragen und führen diese einmal aus, um Sie dem Cache hinzuzufügen (wenn das Caching aktiviert ist).In this test, we first iterate through the list of queries and execute each one once to add them to the cache (if caching is enabled). Dieser Schritt ist nicht geplant.This step is untimed. Als nächstes wird der Haupt Thread für mehr als 60 Sekunden in den Standbymodus versetzt, um das Zwischenspeichern von Caches zuzulassen. zum Schluss durchlaufen wir die Liste ein zweites Mal, um die zwischengespeicherten Abfragen auszuführen.Next, we sleep the main thread for over 60 seconds to allow cache sweeping to take place; finally, we iterate through the list a 2nd time to execute the cached queries. Außerdem wird der SQL Server Plancache geleert, bevor jeder Satz von Abfragen ausgeführt wird, sodass die Zeiten, die der Abfrageplan Cache liefert, genau wiedergegeben werden.Additionally, the SQL Server plan cache is flushed before each set of queries is executed so that the times we obtain accurately reflect the benefit given by the query plan cache.

3.2.3.1 Testergebnisse3.2.3.1       Test Results
TestTest EF5 kein CacheEF5 no cache EF5 zwischengespeichertEF5 cached EF6 kein CacheEF6 no cache EF6 zwischengespeichertEF6 cached
Auflisten aller 18723-AbfragenEnumerating all 18723 queries 124124 125,4125.4 124,3124.3 125,3125.3
Vermeiden von Sweep (nur die ersten 800-Abfragen, unabhängig von der Komplexität)Avoiding sweep (just the first 800 queries, regardless of complexity) 41,741.7 5.55.5 40,540.5 5.45.4
Nur die aggregatingsubsummen-Abfragen (178 Total, wodurch das Sweep vermieden wird)Just the AggregatingSubtotals queries (178 total - which avoids sweep) 39,539.5 4,54.5 38,138.1 4.64.6

Alle Uhrzeiten in Sekunden.All times in seconds.

Moralisch: beim Ausführen von vielen unterschiedlichen Abfragen (z. b. dynamisch erstellte Abfragen) ist das Caching nicht hilfreich, und die daraus resultierende Speicherung des Caches kann die Abfragen, die am meisten von der Zwischenspeicherung des Plans profitieren, von der eigentlichen Verwendung der Abfrage behalten.Moral - when executing lots of distinct queries (for example,  dynamically created queries), caching doesn't help and the resulting flushing of the cache can keep the queries that would benefit the most from plan caching from actually using it.

Die aggregatingsubsummen-Abfragen sind die komplexesten der Abfragen, die wir mit getestet haben.The AggregatingSubtotals queries are the most complex of the queries we tested with. Je komplexer die Abfrage ist, desto komplexer wird der Zwischenspeicher des Abfrage Plans.As expected, the more complex the query is, the more benefit you will see from query plan caching.

Da es sich bei einer CompiledQuery tatsächlich um eine LINQ-Abfrage handelt, bei der der Plan zwischengespeichert ist, sollte der Vergleich einer CompiledQuery und der entsprechenden Entity SQL Abfrage ähnliche Ergebnisse aufweisen.Because a CompiledQuery is really a LINQ query with its plan cached, the comparison of a CompiledQuery versus the equivalent Entity SQL query should have similar results. Wenn eine APP viele dynamische Entity SQL Abfragen enthält, führt das Auffüllen des Caches mit Abfragen auch dazu, dass compiledqueries beim leeren aus dem Cache "deaktiviert" wird.In fact, if an app has lots of dynamic Entity SQL queries, filling the cache with queries will also effectively cause CompiledQueries to “decompile” when they are flushed from the cache. In diesem Szenario kann die Leistung verbessert werden, indem das Zwischenspeichern für die dynamischen Abfragen deaktiviert wird, um die compiledqueries zu priorisieren.In this scenario, performance may be improved by disabling caching on the dynamic queries to prioritize the CompiledQueries. Noch besser wäre es, die APP neu zu schreiben, um parametrisierte Abfragen anstelle dynamischer Abfragen zu verwenden.Better yet, of course, would be to rewrite the app to use parameterized queries instead of dynamic queries.

3,3 Verwenden von CompiledQuery zum Verbessern der Leistung mit LINQ-Abfragen3.3 Using CompiledQuery to improve performance with LINQ queries

Unsere Tests deuten darauf hin, dass die Verwendung von CompiledQuery bei automatisch kompilierten LINQ-Abfragen einen Vorteil von 7% haben kann. Dies bedeutet, dass Sie 7% weniger Zeit für das Ausführen von Code aus dem Entity Framework Stapel aufwenden müssen. Dies bedeutet nicht, dass Ihre Anwendung 7% schneller ist.Our tests indicate that using CompiledQuery can bring a benefit of 7% over autocompiled LINQ queries; this means that you’ll spend 7% less time executing code from the Entity Framework stack; it does not mean your application will be 7% faster. Im Allgemeinen sind die Kosten für das Schreiben und warten von CompiledQuery-Objekten in EF 5,0 im Vergleich zu den Vorteilen möglicherweise nicht so schwierig.Generally speaking, the cost of writing and maintaining CompiledQuery objects in EF 5.0 may not be worth the trouble when compared to the benefits. Der Meilenstein kann variieren. führen Sie daher diese Option aus, wenn das Projekt den zusätzlichen Push erfordert.Your mileage may vary, so exercise this option if your project requires the extra push. Beachten Sie, dass compiledqueries nur mit von ObjectContext abgeleiteten Modellen kompatibel sind und nicht mit von dbcontext abgeleiteten Modellen kompatibel ist.Note that CompiledQueries are only compatible with ObjectContext-derived models, and not compatible with DbContext-derived models.

Weitere Informationen zum Erstellen und Aufrufen einer CompiledQuery finden Sie unter kompilierte Abfragen (LINQ to Entities).For more information on creating and invoking a CompiledQuery, see Compiled Queries (LINQ to Entities).

Bei der Verwendung einer CompiledQuery müssen Sie zwei Aspekte beachten, nämlich die Anforderung, statische Instanzen zu verwenden, und die Probleme, die Sie mit der Zusammensetz barkeit haben.There are two considerations you have to take when using a CompiledQuery, namely the requirement to use static instances and the problems they have with composability. Im folgenden finden Sie eine ausführliche Erläuterung dieser beiden Überlegungen.Here follows an in-depth explanation of these two considerations.

3.3.1 Verwenden statischer CompiledQuery-Instanzen3.3.1       Use static CompiledQuery instances

Da das Kompilieren einer LINQ-Abfrage ein zeitaufwändiger Prozess ist, möchten wir Sie nicht jedes Mal durchführen, wenn Daten aus der Datenbank abgerufen werden müssen.Since compiling a LINQ query is a time-consuming process, we don’t want to do it every time we need to fetch data from the database. Mit CompiledQuery-Instanzen können Sie eine einmalige Kompilierung ausführen und mehrmals ausführen, aber Sie müssen darauf achten, dass Sie jedes Mal dieselbe CompiledQuery-Instanz wieder verwenden, anstatt Sie immer wieder zu kompilieren.CompiledQuery instances allow you to compile once and run multiple times, but you have to be careful and procure to re-use the same CompiledQuery instance every time instead of compiling it over and over again. Die Verwendung statischer Member zum Speichern der CompiledQuery-Instanzen wird benötigt. Andernfalls wird kein Vorteil angezeigt.The use of static members to store the CompiledQuery instances becomes necessary; otherwise you won’t see any benefit.

Nehmen Sie beispielsweise an, dass Ihre Seite den folgenden Methoden Text enthält, mit dem die Produkte für die ausgewählte Kategorie angezeigt werden:For example, suppose your page has the following method body to handle displaying the products for the selected category:

    // Warning: this is the wrong way of using CompiledQuery
    using (NorthwindEntities context = new NorthwindEntities())
    {
        string selectedCategory = this.categoriesList.SelectedValue;

        var productsForCategory = CompiledQuery.Compile<NorthwindEntities, string, IQueryable<Product>>(
            (NorthwindEntities nwnd, string category) =>
                nwnd.Products.Where(p => p.Category.CategoryName == category)
        );

        this.productsGrid.DataSource = productsForCategory.Invoke(context, selectedCategory).ToList();
        this.productsGrid.DataBind();
    }

    this.productsGrid.Visible = true;

In diesem Fall erstellen Sie jedes Mal, wenn die-Methode aufgerufen wird, eine neue CompiledQuery-Instanz.In this case, you will create a new CompiledQuery instance on the fly every time the method is called. Anstatt die Leistungsvorteile durch Abrufen des Speicher Befehls aus dem Abfrageplan Cache zu erkennen, durchläuft CompiledQuery den Plan Compiler jedes Mal, wenn eine neue Instanz erstellt wird.Instead of seeing performance benefits by retrieving the store command from the query plan cache, the CompiledQuery will go through the plan compiler every time a new instance is created. Tatsächlich wird der Abfrageplan Cache durch einen neuen CompiledQuery-Eintrag bei jedem Aufruf der-Methode verschmutzt.In fact, you will be polluting your query plan cache with a new CompiledQuery entry every time the method is called.

Stattdessen möchten Sie eine statische Instanz der kompilierten Abfrage erstellen, sodass Sie bei jedem Aufruf der Methode dieselbe kompilierte Abfrage aufrufen.Instead, you want to create a static instance of the compiled query, so you are invoking the same compiled query every time the method is called. Eine Möglichkeit hierfür besteht darin, die CompiledQuery-Instanz als Member des Objekt Kontexts hinzuzufügen.One way to so this is by adding the CompiledQuery instance as a member of your object context.Sie können dann etwas sauberer machen, indem Sie auf die CompiledQuery über eine Hilfsmethode zugreifen:  You can then make things a little cleaner by accessing the CompiledQuery through a helper method:

    public partial class NorthwindEntities : ObjectContext
    {
        private static readonly Func<NorthwindEntities, string, IEnumerable<Product>> productsForCategoryCQ = CompiledQuery.Compile(
            (NorthwindEntities context, string categoryName) =>
                context.Products.Where(p => p.Category.CategoryName == categoryName)
            );

        public IEnumerable<Product> GetProductsForCategory(string categoryName)
        {
            return productsForCategoryCQ.Invoke(this, categoryName).ToList();
        }

Diese Hilfsmethode wird wie folgt aufgerufen:This helper method would be invoked as follows:

    this.productsGrid.DataSource = context.GetProductsForCategory(selectedCategory);

3.3.2 Komposition über eine CompiledQuery3.3.2       Composing over a CompiledQuery

Die Möglichkeit zum Verfassen von LINQ-Abfragen ist äußerst nützlich. Dazu rufen Sie einfach eine Methode nach dem iquerable-Element auf, z. b. Skip () oder count ().The ability to compose over any LINQ query is extremely useful; to do this, you simply invoke a method after the IQueryable such as Skip() or Count(). Dadurch wird jedoch im Grunde ein neues iquerable-Objekt zurückgegeben.However, doing so essentially returns a new IQueryable object. Es gibt zwar nichts, was technisch nicht durch das Verfassen einer CompiledQuery zu tun hat, dies führt jedoch dazu, dass ein neues iquerable-Objekt generiert wird, das den Plan Compiler erneut durchlaufen muss.While there’s nothing to stop you technically from composing over a CompiledQuery, doing so will cause the generation of a new IQueryable object that requires passing through the plan compiler again.

Einige Komponenten verwenden zusammengesetzte iquerable-Objekte, um erweiterte Funktionen zu ermöglichen.Some components will make use of composed IQueryable objects to enable advanced functionality. Beispielsweise ASP. GridView von NET kann an ein iquerable-Objekt über die SelectMethod-Eigenschaft gebunden werden.For example, ASP.NET’s GridView can be data-bound to an IQueryable object via the SelectMethod property. Die GridView wird dann über dieses iquerable-Objekt erstellt, um das Sortieren und Paging über das Datenmodell zuzulassen.The GridView will then compose over this IQueryable object to allow sorting and paging over the data model. Wie Sie sehen, würde die Verwendung einer CompiledQuery für die GridView nicht die kompilierte Abfrage erreichen, sondern eine neue automatisch kompilierte Abfrage generieren.As you can see, using a CompiledQuery for the GridView would not hit the compiled query but would generate a new autocompiled query.

Ein Ort, an dem Sie möglicherweise darauf stoßen, ist das Hinzufügen progressiver Filter zu einer Abfrage.One place where you may run into this is when adding progressive filters to a query. Angenommen, Sie haben eine Kundenseite mit mehreren Dropdown Listen für optionale Filter (z. b. Country und OrdersCount).For example, suppose you had a Customers page with several drop-down lists for optional filters (for example, Country and OrdersCount). Sie können diese Filter über die iquervable-Ergebnisse einer CompiledQuery-Abfrage verfassen. Dies führt jedoch dazu, dass die neue Abfrage bei jeder Ausführung den Plan Compiler durchläuft.You can compose these filters over the IQueryable results of a CompiledQuery, but doing so will result in the new query going through the plan compiler every time you execute it.

    using (NorthwindEntities context = new NorthwindEntities())
    {
        IQueryable<Customer> myCustomers = context.InvokeCustomersForEmployee();

        if (this.orderCountFilterList.SelectedItem.Value != defaultFilterText)
        {
            int orderCount = int.Parse(orderCountFilterList.SelectedValue);
            myCustomers = myCustomers.Where(c => c.Orders.Count > orderCount);
        }

        if (this.countryFilterList.SelectedItem.Value != defaultFilterText)
        {
            myCustomers = myCustomers.Where(c => c.Address.Country == countryFilterList.SelectedValue);
        }

        this.customersGrid.DataSource = myCustomers;
        this.customersGrid.DataBind();
    }

 Um diese Neukompilierung zu vermeiden, können Sie CompiledQuery umschreiben, um die möglichen Filter zu berücksichtigen:To avoid this re-compilation, you can rewrite the CompiledQuery to take the possible filters into account:

    private static readonly Func<NorthwindEntities, int, int?, string, IQueryable<Customer>> customersForEmployeeWithFiltersCQ = CompiledQuery.Compile(
        (NorthwindEntities context, int empId, int? countFilter, string countryFilter) =>
            context.Customers.Where(c => c.Orders.Any(o => o.EmployeeID == empId))
            .Where(c => countFilter.HasValue == false || c.Orders.Count > countFilter)
            .Where(c => countryFilter == null || c.Address.Country == countryFilter)
        );

Dies wird in der Benutzeroberfläche wie folgt aufgerufen:Which would be invoked in the UI like:

    using (NorthwindEntities context = new NorthwindEntities())
    {
        int? countFilter = (this.orderCountFilterList.SelectedIndex == 0) ?
            (int?)null :
            int.Parse(this.orderCountFilterList.SelectedValue);

        string countryFilter = (this.countryFilterList.SelectedIndex == 0) ?
            null :
            this.countryFilterList.SelectedValue;

        IQueryable<Customer> myCustomers = context.InvokeCustomersForEmployeeWithFilters(
                countFilter, countryFilter);

        this.customersGrid.DataSource = myCustomers;
        this.customersGrid.DataBind();
    }

 Ein Kompromiss besteht darin, dass der generierte Speicher Befehl immer die Filter mit den Null-Überprüfungen enthält. diese müssen jedoch für die Optimierung des Datenbankservers recht einfach sein:A tradeoff here is the generated store command will always have the filters with the null checks, but these should be fairly simple for the database server to optimize:

...
WHERE ((0 = (CASE WHEN (@p__linq__1 IS NOT NULL) THEN cast(1 as bit) WHEN (@p__linq__1 IS NULL) THEN cast(0 as bit) END)) OR ([Project3].[C2] > @p__linq__2)) AND (@p__linq__3 IS NULL OR [Project3].[Country] = @p__linq__4)

3,4 Zwischenspeichern von Metadaten3.4 Metadata caching

Der Entity Framework unterstützt auch das Zwischenspeichern von Metadaten.The Entity Framework also supports Metadata caching. Dabei handelt es sich im Wesentlichen um das Zwischenspeichern von Typinformationen und Typdaten für die Daten Bank Zuordnung über verschiedene Verbindungen zum gleichen Modell.This is essentially caching of type information and type-to-database mapping information across different connections to the same model. Der Metadatencache ist pro AppDomain eindeutig.The Metadata cache is unique per AppDomain.

3.4.1 Metadata Caching-Algorithmus3.4.1 Metadata Caching algorithm

  1. Metadateninformationen für ein Modell werden in einer ItemCollection für jede EntityConnection gespeichert.Metadata information for a model is stored in an ItemCollection for each EntityConnection.

    • Als neben Hinweis gibt es verschiedene ItemCollection-Objekte für verschiedene Teile des Modells.As a side note, there are different ItemCollection objects for different parts of the model. Storeitemcollections enthält z. b. die Informationen zum Datenbankmodell. ObjectItemCollection enthält Informationen zum Datenmodell. EdmItemCollection enthält Informationen über das konzeptionelle Modell.For example, StoreItemCollections contains the information about the database model; ObjectItemCollection contains information about the data model; EdmItemCollection contains information about the conceptual model.
  2. Wenn zwei Verbindungen dieselbe Verbindungs Zeichenfolge verwenden, verwenden Sie dieselbe ItemCollection-Instanz.If two connections use the same connection string, they will share the same ItemCollection instance.

  3. Funktionale Äquivalente, aber texell unterschiedliche Verbindungs Zeichenfolgen können zu unterschiedlichen Metadatencaches führen.Functionally equivalent but textually different connection strings may result in different metadata caches. Verbindungs Zeichenfolgen werden mit Token versehen, sodass das Ändern der Reihenfolge der Token zu freigegebenen Metadaten führen sollte.We do tokenize connection strings, so simply changing the order of the tokens should result in shared metadata. Zwei Verbindungs Zeichenfolgen, die funktionstüchtig erscheinen, werden jedoch möglicherweise nach der Tokenisierung nicht als identisch ausgewertet.But two connection strings that seem functionally the same may not be evaluated as identical after tokenization.

  4. Die ItemCollection wird regelmäßig zur Verwendung überprüft.The ItemCollection is periodically checked for use. Wenn festgestellt wird, dass in jüngster Zeit kein Zugriff auf einen Arbeitsbereich erfolgt ist, wird er beim nächsten Cache Sweep für die Bereinigung gekennzeichnet.If it is determined that a workspace has not been accessed recently, it will be marked for cleanup on the next cache sweep.

  5. Die bloße Erstellung einer EntityConnection bewirkt, dass ein Metadatencache erstellt wird (obwohl die Element Auflistungen darin erst nach dem Öffnen der Verbindung initialisiert werden).Merely creating an EntityConnection will cause a metadata cache to be created (though the item collections in it will not be initialized until the connection is opened). Dieser Arbeitsbereich verbleibt im Arbeitsspeicher, bis der Cache Algorithmus festlegt, dass er nicht verwendet wird.This workspace will remain in-memory until the caching algorithm determines it is not “in use”.

Das Customer Advisory Team hat einen Blogbeitrag geschrieben, in dem beschrieben wird, wie Sie einen Verweis auf eine ItemCollection enthalten, um die "Veraltung" bei der Verwendung von großen Modellen zu vermeiden: <https://docs.microsoft.com/archive/blogs/appfabriccat/holding-a-reference-to-the-ef-metadataworkspace-for-wcf-services> .The Customer Advisory Team has written a blog post that describes holding a reference to an ItemCollection in order to avoid "deprecation" when using large models: <https://docs.microsoft.com/archive/blogs/appfabriccat/holding-a-reference-to-the-ef-metadataworkspace-for-wcf-services>.

3.4.2 Beziehung zwischen dem Zwischenspeichern von Metadaten und dem Zwischenspeichern von Abfrage Plänen3.4.2 The relationship between Metadata Caching and Query Plan Caching

Die Abfrageplan Cache-Instanz befindet sich in der ItemCollection des MetadataWorkspace der Speichertypen.The query plan cache instance lives in the MetadataWorkspace's ItemCollection of store types. Dies bedeutet, dass zwischengespeicherte Speicher Befehle für Abfragen für jeden Kontext verwendet werden, der mit einem bestimmten MetadataWorkspace instanziiert wird.This means that cached store commands will be used for queries against any context instantiated using a given MetadataWorkspace. Dies bedeutet auch, dass bei zwei Verbindungs Zeichenfolgen, die sich geringfügig unterscheiden und nach dem tokenisierungsplan nicht abgeglichen werden, verschiedene Abfrageplan Cache Instanzen vorhanden sind.It also means that if you have two connections strings that are slightly different and don't match after tokenizing, you will have different query plan cache instances.

3,5 Ergebnisse Caching3.5 Results caching

Mit dem Zwischenspeichern von Ergebnissen (auch als "Caching auf zweiter Ebene" bezeichnet) behalten Sie die Ergebnisse der Abfragen in einem lokalen Cache bei.With results caching (also known as "second-level caching"), you keep the results of queries in a local cache. Wenn Sie eine Abfrage ausgeben, sehen Sie zunächst, ob die Ergebnisse lokal verfügbar sind, bevor Sie den Speicher Abfragen.When issuing a query, you first see if the results are available locally before you query against the store. Während das Zwischenspeichern von Ergebnissen nicht direkt von Entity Framework unterstützt wird, ist es möglich, einen Cache der zweiten Ebene mithilfe eines Wrapping Anbieters hinzuzufügen.While results caching isn't directly supported by Entity Framework, it's possible to add a second level cache by using a wrapping provider. Ein Beispiel für einen Wrapping Anbieter mit einem Cache der zweiten Ebene ist der auf NCache basierende Cache für Entity Framework Sekunde auf zweiter Ebene auf der zweitenEbene.An example wrapping provider with a second-level cache is Alachisoft's Entity Framework Second Level Cache based on NCache.

Diese Implementierung des zwischen Speicherns auf zweiter Ebene ist eine eingefügte Funktionalität, die ausgeführt wird, nachdem der LINQ-Ausdruck ausgewertet (und funcletisiert) wurde und der Abfrage Ausführungsplan berechnet oder aus dem Cache der ersten Ebene abgerufen wurde.This implementation of second-level caching is an injected functionality that takes place after the LINQ expression has been evaluated (and funcletized) and the query execution plan is computed or retrieved from the first-level cache. Der Cache der zweiten Ebene speichert dann nur die unformatierten Daten Bank Ergebnisse, sodass die Materialisierungs Pipeline nach wie vor ausgeführt wird.The second-level cache will then store only the raw database results, so the materialization pipeline still executes afterwards.

3.5.1 zusätzliche Verweise für das Zwischenspeichern von Ergebnissen mit dem Wrapping Anbieter3.5.1 Additional references for results caching with the wrapping provider

  • Julie Lerman hat im MSDN-Artikel "Caching der zweiten Ebene in Entity Framework und Windows Azure" das Aktualisieren des Beispiel-Wrapping Anbieters für die Verwendung von Windows Server AppFabric Caching erläutert: https://msdn.microsoft.com/magazine/hh394143.aspxJulie Lerman has written a "Second-Level Caching in Entity Framework and Windows Azure" MSDN article that includes how to update the sample wrapping provider to use Windows Server AppFabric caching: https://msdn.microsoft.com/magazine/hh394143.aspx
  • Wenn Sie mit Entity Framework 5 arbeiten, enthält der Teamblog einen Beitrag, in dem beschrieben wird, wie Sie mit dem Caching-Anbieter für Entity Framework 5: Ausführen <https://docs.microsoft.com/archive/blogs/adonet/ef-caching-with-jarek-kowalskis-provider> .If you are working with Entity Framework 5, the team blog has a post that describes how to get things running with the caching provider for Entity Framework 5: <https://docs.microsoft.com/archive/blogs/adonet/ef-caching-with-jarek-kowalskis-provider>. Außerdem enthält Sie eine T4-Vorlage, mit der Sie das Zwischenspeichern der zweiten Ebene zu Ihrem Projekt automatisieren können.It also includes a T4 template to help automate adding the 2nd-level caching to your project.

4 automatisch kompilierte Abfragen4 Autocompiled Queries

Wenn eine Abfrage für eine Datenbank mithilfe von Entity Framework ausgegeben wird, muss Sie eine Reihe von Schritten durchlaufen, bevor die Ergebnisse tatsächlich materialisiert werden. ein solcher Schritt ist die Abfrage Kompilierung.When a query is issued against a database using Entity Framework, it must go through a series of steps before actually materializing the results; one such step is Query Compilation. Entity SQL-Abfragen haben bekanntermaßen eine gute Leistung, da Sie automatisch zwischengespeichert werden. Wenn Sie also die gleiche Abfrage ausführen, können Sie den Plan Compiler überspringen und stattdessen den zwischengespeicherten Plan verwenden.Entity SQL queries were known to have good performance as they are automatically cached, so the second or third time you execute the same query it can skip the plan compiler and use the cached plan instead.

In Entity Framework 5 wurde auch das automatische Zwischenspeichern für LINQ to Entities Abfragen eingeführt.Entity Framework 5 introduced automatic caching for LINQ to Entities queries as well. In früheren Editionen von Entity Framework das Erstellen einer CompiledQuery zum beschleunigen ihrer Leistung eine gängige Vorgehensweise, da dadurch die LINQ to Entities Abfrage zwischengespeichert werden konnte.In past editions of Entity Framework creating a CompiledQuery to speed your performance was a common practice, as this would make your LINQ to Entities query cacheable. Da das Caching jetzt ohne Verwendung von CompiledQuery automatisch erfolgt, wird dieses Feature als "automatisch kompilierte Abfragen" bezeichnet.Since caching is now done automatically without the use of a CompiledQuery, we call this feature “autocompiled queries”. Weitere Informationen über den Abfrageplan Cache und seine Mechanismen finden Sie unter Zwischenspeichern von Abfrage Plänen.For more information about the query plan cache and its mechanics, see Query Plan Caching.

Entity Framework erkennt, wenn eine Abfrage erneut kompiliert werden muss. Dies geschieht auch, wenn die Abfrage aufgerufen wird, auch wenn Sie zuvor kompiliert wurde.Entity Framework detects when a query requires to be recompiled, and does so when the query is invoked even if it had been compiled before. Folgende häufige Bedingungen bewirken, dass die Abfrage neu kompiliert wird:Common conditions that cause the query to be recompiled are:

  • Ändern der MergeOption, die der Abfrage zugeordnet ist.Changing the MergeOption associated to your query. Die zwischengespeicherte Abfrage wird nicht verwendet, sondern der Plan Compiler wird erneut ausgeführt, und der neu erstellte Plan wird zwischengespeichert.The cached query will not be used, instead the plan compiler will run again and the newly created plan gets cached.
  • Ändern des Werts von ContextOptions. usecsharpnullcomparisonbehavior.Changing the value of ContextOptions.UseCSharpNullComparisonBehavior. Sie erhalten die gleichen Auswirkungen wie das Ändern der MergeOption.You get the same effect as changing the MergeOption.

Andere Bedingungen können verhindern, dass Ihre Abfrage den Cache verwendet.Other conditions can prevent your query from using the cache. Typische Beispiele:Common examples are:

  • Verwenden von IEnumerable < T > . Enthält < > (T-Wert).Using IEnumerable<T>.Contains<>(T value).
  • Verwenden von Funktionen, mit denen Abfragen mit Konstanten erzeugt werden.Using functions that produce queries with constants.
  • Verwenden der Eigenschaften eines nicht zugeordneten Objekts.Using the properties of a non-mapped object.
  • Verknüpfen der Abfrage mit einer anderen Abfrage, für die eine erneute Kompilierung erforderlich ist.Linking your query to another query that requires to be recompiled.

4,1 Verwenden von IEnumerable < T > . Enthält < t > (t-Wert)4.1 Using IEnumerable<T>.Contains<T>(T value)

In Entity Framework werden keine Abfragen zwischengespeichert, die IEnumerable < T aufrufen > . Enthält < t > (t-Wert) für eine Auflistung im Arbeitsspeicher, da die Werte der Auflistung als flüchtig angesehen werden.Entity Framework does not cache queries that invoke IEnumerable<T>.Contains<T>(T value) against an in-memory collection, since the values of the collection are considered volatile. Die folgende Beispiel Abfrage wird nicht zwischengespeichert, sodass Sie immer vom Plan Compiler verarbeitet wird:The following example query will not be cached, so it will always be processed by the plan compiler:

int[] ids = new int[10000];
...
using (var context = new MyContext())
{
    var query = context.MyEntities
                    .Where(entity => ids.Contains(entity.Id));

    var results = query.ToList();
    ...
}

Beachten Sie, dass die Größe des IEnumerable-Element, in dem enthalten ist, bestimmt, wie schnell oder wie langsam die Abfrage kompiliert wird.Note that the size of the IEnumerable against which Contains is executed determines how fast or how slow your query is compiled. Die Leistung kann erheblich beeinträchtigt werden, wenn große Auflistungen verwendet werden, wie im obigen Beispiel gezeigt.Performance can suffer significantly when using large collections such as the one shown in the example above.

Entity Framework 6 enthält Optimierungen, wie IEnumerable < T > . Enthält < t > (t-Wert) funktioniert, wenn Abfragen ausgeführt werden.Entity Framework 6 contains optimizations to the way IEnumerable<T>.Contains<T>(T value) works when queries are executed. Der generierte SQL-Code ist viel schneller zu erzeugen und lesbarer zu machen, und in den meisten Fällen wird er auch schneller auf dem Server ausgeführt.The SQL code that is generated is much faster to produce and more readable, and in most cases it also executes faster in the server.

4,2 Verwenden von Funktionen, die Abfragen mit Konstanten entwickeln4.2 Using functions that produce queries with constants

Die LINQ-Operatoren Skip (), Take (), enthält () und defautifempty () erstellen keine SQL-Abfragen mit Parametern, sondern legen die an Sie übergebenen Werte als Konstanten fest.The Skip(), Take(), Contains() and DefautIfEmpty() LINQ operators do not produce SQL queries with parameters but instead put the values passed to them as constants. Aus diesem Grund werden Abfragen, die andernfalls identisch sein könnten, den Abfrageplan Cache sowohl auf dem EF-Stapel als auch auf dem Datenbankserver verschmutzen und werden nicht wieder hergestellt, es sei denn, in einer nachfolgenden Abfrage Ausführung werden dieselben Konstanten verwendet.Because of this, queries that might otherwise be identical end up polluting the query plan cache, both on the EF stack and on the database server, and do not get reutilized unless the same constants are used in a subsequent query execution. Beispiel:For example:

var id = 10;
...
using (var context = new MyContext())
{
    var query = context.MyEntities.Select(entity => entity.Id).Contains(id);

    var results = query.ToList();
    ...
}

In diesem Beispiel wird jedes Mal, wenn diese Abfrage mit einem anderen Wert für ID ausgeführt wird, die Abfrage in einen neuen Plan kompiliert.In this example, each time this query is executed with a different value for id the query will be compiled into a new plan.

Achten Sie insbesondere auf die Verwendung von Skip und Take beim Paging.In particular pay attention to the use of Skip and Take when doing paging. In EF6 verfügen diese Methoden über eine Lambda Überladung, die den zwischengespeicherten Abfrageplan effektiv wiederverwendbar macht, da EF an diese Methoden übergebenen Variablen erfassen und in SQLPARAMETERS übersetzen kann.In EF6 these methods have a lambda overload that effectively makes the cached query plan reusable because EF can capture variables passed to these methods and translate them to SQLparameters. Dies trägt auch dazu bei, den Cache zu bereinigen, da andernfalls jede Abfrage mit einer anderen Konstante für Skip und Take einen eigenen Cache Eintrag für den Abfrageplan erhalten würde.This also helps keep the cache cleaner since otherwise each query with a different constant for Skip and Take would get its own query plan cache entry.

Sehen Sie sich den folgenden Code an, der nicht optimal ist, aber nur für die Veranschaulichung dieser Abfrage Klasse vorgesehen ist:Consider the following code, which is suboptimal but is only meant to exemplify this class of queries:

var customers = context.Customers.OrderBy(c => c.LastName);
for (var i = 0; i < count; ++i)
{
    var currentCustomer = customers.Skip(i).FirstOrDefault();
    ProcessCustomer(currentCustomer);
}

Eine schnellere Version desselben Codes umfasst das Aufrufen von Skip mit einem Lambda-Ausdruck:A faster version of this same code would involve calling Skip with a lambda:

var customers = context.Customers.OrderBy(c => c.LastName);
for (var i = 0; i < count; ++i)
{
    var currentCustomer = customers.Skip(() => i).FirstOrDefault();
    ProcessCustomer(currentCustomer);
}

Der zweite Ausschnitt kann bis zu 11% schneller ausgeführt werden, da derselbe Abfrageplan bei jedem Ausführen der Abfrage verwendet wird. Dadurch wird die CPU-Zeit gespart, und der Abfragecache wird vermieden.The second snippet may run up to 11% faster because the same query plan is used every time the query is run, which saves CPU time and avoids polluting the query cache. Da der zu über springende Parameter in einem Abschluss liegt, könnte der Code nun wie folgt aussehen:Furthermore, because the parameter to Skip is in a closure the code might as well look like this now:

var i = 0;
var skippyCustomers = context.Customers.OrderBy(c => c.LastName).Skip(() => i);
for (; i < count; ++i)
{
    var currentCustomer = skippyCustomers.FirstOrDefault();
    ProcessCustomer(currentCustomer);
}

4,3 Verwenden der Eigenschaften eines nicht zugeordneten Objekts4.3 Using the properties of a non-mapped object

Wenn eine Abfrage die Eigenschaften eines nicht zugeordneten Objekt Typs als Parameter verwendet, wird die Abfrage nicht zwischengespeichert.When a query uses the properties of a non-mapped object type as a parameter then the query will not get cached. Beispiel:For example:

using (var context = new MyContext())
{
    var myObject = new NonMappedType();

    var query = from entity in context.MyEntities
                where entity.Name.StartsWith(myObject.MyProperty)
                select entity;

   var results = query.ToList();
    ...
}

Nehmen Sie in diesem Beispiel an, dass die Klasse nonmappedtype nicht Teil des Entitäts Modells ist.In this example, assume that class NonMappedType is not part of the Entity model. Diese Abfrage kann problemlos so geändert werden, dass kein nicht zugeordneter Typ verwendet wird, sondern stattdessen eine lokale Variable als Parameter für die Abfrage verwendet wird:This query can easily be changed to not use a non-mapped type and instead use a local variable as the parameter to the query:

using (var context = new MyContext())
{
    var myObject = new NonMappedType();
    var myValue = myObject.MyProperty;
    var query = from entity in context.MyEntities
                where entity.Name.StartsWith(myValue)
                select entity;

    var results = query.ToList();
    ...
}

In diesem Fall kann die Abfrage zwischengespeichert werden und profitiert vom Abfrageplan Cache.In this case, the query will be able to get cached and will benefit from the query plan cache.

4,4 verknüpfen mit Abfragen, die eine erneute Kompilierung erfordern4.4 Linking to queries that require recompiling

Wenn Sie über eine zweite Abfrage verfügen, die auf einer Abfrage basiert, die erneut kompiliert werden muss, wird das gleiche Beispiel wie oben beschrieben.Following the same example as above, if you have a second query that relies on a query that needs to be recompiled, your entire second query will also be recompiled. Es folgt ein Beispiel zur Veranschaulichung dieses Szenarios:Here’s an example to illustrate this scenario:

int[] ids = new int[10000];
...
using (var context = new MyContext())
{
    var firstQuery = from entity in context.MyEntities
                        where ids.Contains(entity.Id)
                        select entity;

    var secondQuery = from entity in context.MyEntities
                        where firstQuery.Any(otherEntity => otherEntity.Id == entity.Id)
                        select entity;

    var results = secondQuery.ToList();
    ...
}

Das Beispiel ist generisch, aber es veranschaulicht, wie die Verknüpfung mit firstquery bewirkt, dass secondquery nicht zwischengespeichert wird.The example is generic, but it illustrates how linking to firstQuery is causing secondQuery to be unable to get cached. Wenn firstquery keine Abfrage war, die eine erneute Kompilierung erfordert, wurde secondquery zwischengespeichert.If firstQuery had not been a query that requires recompiling, then secondQuery would have been cached.

5 NoTracking-Abfragen5 NoTracking Queries

5,1 Deaktivieren der Änderungs Nachverfolgung, um den Status Verwaltungsaufwand zu reduzieren5.1 Disabling change tracking to reduce state management overhead

Wenn Sie in einem schreibgeschützten Szenario arbeiten und den mehr Aufwand beim Laden der Objekte in den objectstatus Manager vermeiden möchten, können Sie keine nach Verfolgungs Abfragen ausgeben.If you are in a read-only scenario and want to avoid the overhead of loading the objects into the ObjectStateManager, you can issue "No Tracking" queries.Die Änderungs Nachverfolgung kann auf Abfrage Ebene deaktiviert werden.  Change tracking can be disabled at the query level.

Beachten Sie jedoch, dass Sie durch das Deaktivieren der Änderungs Nachverfolgung den Objekt Cache tatsächlich ausschalten.Note though that by disabling change tracking you are effectively turning off the object cache. Wenn Sie eine Abfrage für eine Entität durchführen, können Sie die Materialisierung nicht überspringen, indem Sie die zuvor materialisierten Abfrageergebnisse von objectstatus Manager abrufen.When you query for an entity, we can't skip materialization by pulling the previously-materialized query results from the ObjectStateManager. Wenn Sie wiederholt die gleichen Entitäten im gleichen Kontext Abfragen, sehen Sie möglicherweise einen Leistungsvorteil von der Aktivierung der Änderungs Nachverfolgung.If you are repeatedly querying for the same entities on the same context, you might actually see a performance benefit from enabling change tracking.

Bei der Abfrage mithilfe von ObjectContext merken sich die Instanzen von ObjectQuery und ObjectSet eine MergeOption, nachdem Sie festgelegt wurde, und Abfragen, die für Sie erstellt werden, erben die effektive MergeOption der übergeordneten Abfrage.When querying using ObjectContext, ObjectQuery and ObjectSet instances will remember a MergeOption once it is set, and queries that are composed on them will inherit the effective MergeOption of the parent query. Wenn Sie dbcontext verwenden, kann die Überwachung durch Aufrufen des asnotracking ()-Modifizierers für das dbset deaktiviert werden.When using DbContext, tracking can be disabled by calling the AsNoTracking() modifier on the DbSet.

5.1.1 Deaktivierung der Änderungs Nachverfolgung für eine Abfrage bei Verwendung von dbcontext5.1.1 Disabling change tracking for a query when using DbContext

Sie können den Modus einer Abfrage auf NoTracking umstellen, indem Sie in der Abfrage einen aufzurufenden Rückruf der asnotracking ()-Methode verketten.You can switch the mode of a query to NoTracking by chaining a call to the AsNoTracking() method in the query. Anders als bei ObjectQuery haben die dbset-und dbquery-Klassen in der dbcontext-API keine änderbare Eigenschaft für die MergeOption.Unlike ObjectQuery, the DbSet and DbQuery classes in the DbContext API don’t have a mutable property for the MergeOption.

    var productsForCategory = from p in context.Products.AsNoTracking()
                                where p.Category.CategoryName == selectedCategory
                                select p;


5.1.2 Deaktivieren der Änderungs Nachverfolgung auf Abfrage Ebene mithilfe von ObjectContext5.1.2 Disabling change tracking at the query level using ObjectContext

    var productsForCategory = from p in context.Products
                                where p.Category.CategoryName == selectedCategory
                                select p;

    ((ObjectQuery)productsForCategory).MergeOption = MergeOption.NoTracking;

5.1.3 Deaktivieren der Änderungs Nachverfolgung für eine gesamte Entitätenmenge mithilfe von ObjectContext5.1.3 Disabling change tracking for an entire entity set using ObjectContext

    context.Products.MergeOption = MergeOption.NoTracking;

    var productsForCategory = from p in context.Products
                                where p.Category.CategoryName == selectedCategory
                                select p;

5,2 Testmetriken veranschaulichen den Leistungsvorteil von NoTracking-Abfragen5.2 Test Metrics demonstrating the performance benefit of NoTracking queries

In diesem Test betrachten wir die Kosten für das Ausfüllen von objectstatus Manager, indem wir die Nachverfolgung mit NoTracking-Abfragen für das Navision-Modell vergleichen.In this test we look at the cost of filling the ObjectStateManager by comparing Tracking to NoTracking queries for the Navision model. Eine Beschreibung des Navision-Modells und der ausgeführten Abfrage Typen finden Sie im Anhang.See the appendix for a description of the Navision model and the types of queries which were executed. In diesem Test durchlaufen wir die Abfrage Liste und führen jede einzelne aus.In this test, we iterate through the list of queries and execute each one once. Wir haben zwei Variationen des Tests ausgeführt, einmal mit NoTracking-Abfragen und einmal mit der Standard Zusammenfassungs Option "AppendOnly".We ran two variations of the test, once with NoTracking queries and once with the default merge option of "AppendOnly". Wir haben jede Variation dreimal ausgeführt und den Mittelwert der Ausführungen übernommen.We ran each variation 3 times and take the mean value of the runs. Zwischen den Tests löschen wir den Abfragecache auf dem SQL Server und verkleinern tempdb, indem wir die folgenden Befehle ausführen:Between the tests we clear the query cache on the SQL Server and shrink the tempdb by running the following commands:

  1. DBCC DROPCLEANBUFFERSDBCC DROPCLEANBUFFERS
  2. DBCC FREEPROCCACHEDBCC FREEPROCCACHE
  3. DBCC SHRINKDATABASE (tempdb, 0)DBCC SHRINKDATABASE (tempdb, 0)

Testergebnisse, Median über 3 Ausführungen:Test Results, median over 3 runs:

keine Nachverfolgung – WorkingsetNO TRACKING – WORKING SET keine Nachverfolgung – ZeitNO TRACKING – TIME Nur anfügen – WorkingsetAPPEND ONLY – WORKING SET Nur anfügen – ZeitAPPEND ONLY – TIME
Entity Framework 5Entity Framework 5 460361728460361728 1163536 MS1163536 ms 596545536596545536 1273042 MS1273042 ms
Entity Framework 6Entity Framework 6 647127040647127040 190228 MS190228 ms 832798720832798720 195521 MS195521 ms

Entity Framework 5 hat am Ende des Testlaufs einen geringeren Speicherbedarf als Entity Framework 6.Entity Framework 5 will have a smaller memory footprint at the end of the run than Entity Framework 6 does. Der zusätzliche von Entity Framework 6 belegte Arbeitsspeicher ist das Ergebnis zusätzlicher Speicherstrukturen und Code, die neue Features und eine bessere Leistung ermöglichen.The additional memory consumed by Entity Framework 6 is the result of additional memory structures and code that enable new features and better performance.

Bei der Verwendung von objectstatus Manager gibt es auch einen deutlichen Unterschied bei der Speicher Beanspruchung.There’s also a clear difference in memory footprint when using the ObjectStateManager. Entity Framework 5 hat den Speicherbedarf um 30% gesteigert, wenn alle Entitäten nachverfolgt werden, die aus der Datenbank materialisiert wurden.Entity Framework 5 increased its footprint by 30% when keeping track of all the entities we materialized from the database. In Entity Framework 6 wurde der Speicherbedarf um 28% gesteigert.Entity Framework 6 increased its footprint by 28% when doing so.

Im Hinblick auf die Zeit führt Entity Framework 6 Entity Framework 5 in diesem Test um einen großen Rand aus.In terms of time, Entity Framework 6 outperforms Entity Framework 5 in this test by a large margin. Entity Framework 6 hat den Test in ungefähr 16% der von Entity Framework 5 verbrauchten Zeit abgeschlossen.Entity Framework 6 completed the test in roughly 16% of the time consumed by Entity Framework 5. Außerdem nimmt Entity Framework 5 9% mehr Zeit in Anspruch, wenn "objectstatus Manager" verwendet wird.Additionally, Entity Framework 5 takes 9% more time to complete when the ObjectStateManager is being used. Im Vergleich dazu verwendet Entity Framework 6 3% mehr Zeit, wenn objectstatus Manager verwendet wird.In comparison, Entity Framework 6 is using 3% more time when using the ObjectStateManager.

6 Abfrage Ausführungs Optionen6 Query Execution Options

Entity Framework bietet verschiedene Möglichkeiten für die Abfrage.Entity Framework offers several different ways to query. Wir sehen uns die folgenden Optionen an, vergleichen die vor-und Nachteile der einzelnen und überprüfen ihre Leistungsmerkmale:We'll take a look at the following options, compare the pros and cons of each, and examine their performance characteristics:

  • LINQ to Entities.LINQ to Entities.
  • Keine nach Verfolgungs LINQ to Entities.No Tracking LINQ to Entities.
  • Entity SQL über eine ObjectQuery.Entity SQL over an ObjectQuery.
  • Entity SQL über einem EntityCommand.Entity SQL over an EntityCommand.
  • ExecuteStoreQuery.ExecuteStoreQuery.
  • SqlQuery.SqlQuery.
  • CompiledQuery.CompiledQuery.

6,1 LINQ to Entities Abfragen6.1       LINQ to Entities queries

var q = context.Products.Where(p => p.Category.CategoryName == "Beverages");

VorteilePros

  • Geeignet für CUD-Vorgänge.Suitable for CUD operations.
  • Vollständig materialisierte Objekte.Fully materialized objects.
  • Das einfachste schreiben mit Syntax, die in die Programmiersprache integriert ist.Simplest to write with syntax built into the programming language.
  • Gute Leistung.Good performance.

NachteileCons

  • Bestimmte technische Einschränkungen, z. b.:Certain technical restrictions, such as:
    • Muster, die DefaultIfEmpty für äußere joinabfragen verwenden, führen zu komplexeren Abfragen als einfache äußere JOIN-Anweisungen in Entity SQL.Patterns using DefaultIfEmpty for OUTER JOIN queries result in more complex queries than simple OUTER JOIN statements in Entity SQL.
    • Sie können "like" weiterhin nicht mit dem allgemeinen Musterabgleich verwenden.You still can’t use LIKE with general pattern matching.

6,2 keine Nachverfolgung LINQ to Entities Abfragen6.2       No Tracking LINQ to Entities queries

Wenn der Kontext ObjectContext ableitet:When the context derives ObjectContext:

context.Products.MergeOption = MergeOption.NoTracking;
var q = context.Products.Where(p => p.Category.CategoryName == "Beverages");

Wenn der Kontext dbcontext ableitet:When the context derives DbContext:

var q = context.Products.AsNoTracking()
                        .Where(p => p.Category.CategoryName == "Beverages");

VorteilePros

  • Verbesserte Leistung gegenüber regulären LINQ-Abfragen.Improved performance over regular LINQ queries.
  • Vollständig materialisierte Objekte.Fully materialized objects.
  • Das einfachste schreiben mit Syntax, die in die Programmiersprache integriert ist.Simplest to write with syntax built into the programming language.

NachteileCons

  • Nicht geeignet für CUD-Vorgänge.Not suitable for CUD operations.
  • Bestimmte technische Einschränkungen, z. b.:Certain technical restrictions, such as:
    • Muster, die DefaultIfEmpty für äußere joinabfragen verwenden, führen zu komplexeren Abfragen als einfache äußere JOIN-Anweisungen in Entity SQL.Patterns using DefaultIfEmpty for OUTER JOIN queries result in more complex queries than simple OUTER JOIN statements in Entity SQL.
    • Sie können "like" weiterhin nicht mit dem allgemeinen Musterabgleich verwenden.You still can’t use LIKE with general pattern matching.

Beachten Sie, dass Abfragen, die skalare Eigenschaften projizieren, auch dann nicht nachverfolgt werden, wenn NoTracking nicht angegeben ist.Note that queries that project scalar properties are not tracked even if the NoTracking is not specified. Beispiel:For example:

var q = context.Products.Where(p => p.Category.CategoryName == "Beverages").Select(p => new { p.ProductName });

Diese spezielle Abfrage gibt nicht explizit die NoTracking-Angabe an, aber da Sie keinen Typ materialisiert, der dem Objekt Zustands-Manager bekannt ist, wird das materialisierte Ergebnis nicht nachverfolgt.This particular query doesn’t explicitly specify being NoTracking, but since it’s not materializing a type that’s known to the object state manager then the materialized result is not tracked.

6,3 Entity SQL über ObjectQuery6.3       Entity SQL over an ObjectQuery

ObjectQuery<Product> products = context.Products.Where("it.Category.CategoryName = 'Beverages'");

VorteilePros

  • Geeignet für CUD-Vorgänge.Suitable for CUD operations.
  • Vollständig materialisierte Objekte.Fully materialized objects.
  • Unterstützt Zwischenspeichern von Abfrage Plänen.Supports query plan caching.

NachteileCons

  • Umfasst Text Abfrage Zeichenfolgen, die anfälliger für Benutzerfehler sind als in die Sprache integrierte Abfragekonstrukte.Involves textual query strings which are more prone to user error than query constructs built into the language.

6,4 Entity SQL über einen Entitäts Befehl6.4       Entity SQL over an Entity Command

EntityCommand cmd = eConn.CreateCommand();
cmd.CommandText = "Select p From NorthwindEntities.Products As p Where p.Category.CategoryName = 'Beverages'";

using (EntityDataReader reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess))
{
    while (reader.Read())
    {
        // manually 'materialize' the product
    }
}

VorteilePros

  • Unterstützt das Zwischenspeichern von Abfrage Plänen in .NET 4,0 (die Plan Zwischenspeicherung wird von allen anderen Abfrage Typen in .NET 4,5 unterstützt).Supports query plan caching in .NET 4.0 (plan caching is supported by all other query types in .NET 4.5).

NachteileCons

  • Umfasst Text Abfrage Zeichenfolgen, die anfälliger für Benutzerfehler sind als in die Sprache integrierte Abfragekonstrukte.Involves textual query strings which are more prone to user error than query constructs built into the language.
  • Nicht geeignet für CUD-Vorgänge.Not suitable for CUD operations.
  • Die Ergebnisse werden nicht automatisch materialisiert und müssen vom Daten Reader gelesen werden.Results are not automatically materialized, and must be read from the data reader.

6,5 sqlQuery und ExecuteStoreQuery6.5       SqlQuery and ExecuteStoreQuery

SqlQuery für Datenbank:SqlQuery on Database:

// use this to obtain entities and not track them
var q1 = context.Database.SqlQuery<Product>("select * from products");

SqlQuery für dbset:SqlQuery on DbSet:

// use this to obtain entities and have them tracked
var q2 = context.Products.SqlQuery("select * from products");

Execytestorequery:ExecyteStoreQuery:

var beverages = context.ExecuteStoreQuery<Product>(
@"     SELECT        P.ProductID, P.ProductName, P.SupplierID, P.CategoryID, P.QuantityPerUnit, P.UnitPrice, P.UnitsInStock, P.UnitsOnOrder, P.ReorderLevel, P.Discontinued, P.DiscontinuedDate
       FROM            Products AS P INNER JOIN Categories AS C ON P.CategoryID = C.CategoryID
       WHERE        (C.CategoryName = 'Beverages')"
);

VorteilePros

  • Allgemein schnellste Leistung, da der Plan Compiler umgangen wird.Generally fastest performance since plan compiler is bypassed.
  • Vollständig materialisierte Objekte.Fully materialized objects.
  • Eignet sich für CUD-Vorgänge, wenn Sie aus dem dbset verwendet werden.Suitable for CUD operations when used from the DbSet.

NachteileCons

  • Die Abfrage ist Text und fehleranfällig.Query is textual and error prone.
  • Die Abfrage ist an ein bestimmtes Back-End gebunden, indem die Speicher Semantik anstelle der konzeptionellen Semantik verwendet wird.Query is tied to a specific backend by using store semantics instead of conceptual semantics.
  • Wenn eine Vererbung vorhanden ist, muss die abgeforderte Abfrage die Zuordnung von Bedingungen für den angeforderten Typ berücksichtigen.When inheritance is present, handcrafted query needs to account for mapping conditions for the type requested.

6,6 CompiledQuery6.6       CompiledQuery

private static readonly Func<NorthwindEntities, string, IQueryable<Product>> productsForCategoryCQ = CompiledQuery.Compile(
    (NorthwindEntities context, string categoryName) =>
        context.Products.Where(p => p.Category.CategoryName == categoryName)
        );
…
var q = context.InvokeProductsForCategoryCQ("Beverages");

VorteilePros

  • Bietet eine Leistungsverbesserung von bis zu 7% gegenüber regulären LINQ-Abfragen.Provides up to a 7% performance improvement over regular LINQ queries.
  • Vollständig materialisierte Objekte.Fully materialized objects.
  • Geeignet für CUD-Vorgänge.Suitable for CUD operations.

NachteileCons

  • Größere Komplexität und Programmieraufwand.Increased complexity and programming overhead.
  • Die Leistungsverbesserung geht verloren, wenn eine kompilierte Abfrage erstellt wird.The performance improvement is lost when composing on top of a compiled query.
  • Einige LINQ-Abfragen können nicht als CompiledQuery geschrieben werden, z. b. Projektionen anonymer Typen.Some LINQ queries can't be written as a CompiledQuery - for example, projections of anonymous types.

6,7 Leistungsvergleich verschiedener Abfrage Optionen6.7       Performance Comparison of different query options

Einfache Mikrobenchmarks, bei denen die Kontext Erstellung nicht durchgesetzt wurde, wurden in den Test eingefügt.Simple microbenchmarks where the context creation was not timed were put to the test. Wir haben das Abfragen von 5000-mal für eine Reihe von nicht zwischengespeicherten Entitäten in einer kontrollierten Umgebung gemessen.We measured querying 5000 times for a set of non-cached entities in a controlled environment. Diese Zahlen müssen mit einer Warnung erstellt werden: Sie reflektieren nicht die tatsächlichen Zahlen, die von einer Anwendung erzeugt werden, sondern Sie sind ein sehr genaues Maß für den Leistungsunterschied, wenn verschiedene Abfrage Optionen als Äpfel-zu-Äpfel verglichen werden, ausgenommen der Kosten für die Erstellung eines neuen Kontexts.These numbers are to be taken with a warning: they do not reflect actual numbers produced by an application, but instead they are a very accurate measurement of how much of a performance difference there is when different querying options are compared apples-to-apples, excluding the cost of creating a new context.

EFEF TestTest Zeit (MS)Time (ms) ArbeitsspeicherMemory
EF5EF5 ObjectContext ESQLObjectContext ESQL 24142414 3880140838801408
EF5EF5 ObjectContext (LINQ-Abfrage)ObjectContext Linq Query 26922692 3827712038277120
EF5EF5 Dbcontext LINQ-Abfrage keine NachverfolgungDbContext Linq Query No Tracking 28182818 4184064041840640
EF5EF5 Dbcontext-LINQ-AbfrageDbContext Linq Query 29302930 4177100841771008
EF5EF5 ObjectContext LINQ-Abfrage keine NachverfolgungObjectContext Linq Query No Tracking 30133013 3841228838412288
EF6EF6 ObjectContext ESQLObjectContext ESQL 20592059 4603904046039040
EF6EF6 ObjectContext (LINQ-Abfrage)ObjectContext Linq Query 30743074 4524851245248512
EF6EF6 Dbcontext LINQ-Abfrage keine NachverfolgungDbContext Linq Query No Tracking 31253125 4757504047575040
EF6EF6 Dbcontext-LINQ-AbfrageDbContext Linq Query 34203420 4765286447652864
EF6EF6 ObjectContext LINQ-Abfrage keine NachverfolgungObjectContext Linq Query No Tracking 35933593 4526080045260800

EF5 Micro-Benchmarks, 5000-warme Iterationen

EF6 Micro-Benchmarks, 5000-warme Iterationen

Mikrobenchmarks sind sehr empfindlich gegenüber kleinen Änderungen im Code.Microbenchmarks are very sensitive to small changes in the code. In diesem Fall ist der Unterschied zwischen den Kosten von Entity Framework 5 und Entity Framework 6 auf das Hinzufügen von Abfang -und Transaktions Verbesserungenzurückzuführen.In this case, the difference between the costs of Entity Framework 5 and Entity Framework 6 are due to the addition of interception and transactional improvements. Diese Mikrobenchmarks-Zahlen sind jedoch eine verstärkte Vision in einem sehr kleinen Fragment, was Entity Framework tut.These microbenchmarks numbers, however, are an amplified vision into a very small fragment of what Entity Framework does. In realen Szenarien mit warmen Abfragen sollte bei der Aktualisierung von Entity Framework 5 auf Entity Framework 6 keine Leistungs Regression auftreten.Real-world scenarios of warm queries should not see a performance regression when upgrading from Entity Framework 5 to Entity Framework 6.

Um die tatsächliche Leistung der verschiedenen Abfrage Optionen zu vergleichen, haben wir fünf separate Test Variationen erstellt, bei denen wir eine andere Abfrage Option verwenden, um alle Produkte auszuwählen, deren Kategoriename "Beverage" lautet.To compare the real-world performance of the different query options, we created 5 separate test variations where we use a different query option to select all products whose category name is "Beverages". Jede Iterationen umfasst die Kosten für die Erstellung des Kontexts und die Kosten für das Materialisieren aller zurückgegebenen Entitäten.Each iteration includes the cost of creating the context, and the cost of materializing all returned entities. 10 Iterationen werden ohne Zeitüberschreitung ausgeführt, bevor die Summe von 1000 zeitgesteuerten Iterationen übernehmen wird.10 iterations are run untimed before taking the sum of 1000 timed iterations. Die angezeigten Ergebnisse sind die durchschnittliche Ausführung von 5 Ausführungen der einzelnen Tests.The results shown are the median run taken from 5 runs of each test. Weitere Informationen finden Sie in Anhang B, in dem der Code für den Test enthalten ist.For more information, see Appendix B which includes the code for the test.

EFEF TestTest Zeit (MS)Time (ms) ArbeitsspeicherMemory
EF5EF5 ObjectContext-Entitäts BefehlObjectContext Entity Command 621621 3935027239350272
EF5EF5 Dbcontext-SQL-Abfrage für DatenbankDbContext Sql Query on Database 825825 3751936037519360
EF5EF5 ObjectContext-Speicher AbfrageObjectContext Store Query 878878 3946086439460864
EF5EF5 ObjectContext LINQ-Abfrage keine NachverfolgungObjectContext Linq Query No Tracking 969969 3829350438293504
EF5EF5 ObjectContext Entity SQL mit Objekt AbfrageObjectContext Entity Sql using Object Query 10891089 3898163238981632
EF5EF5 Kompilierte ObjectContext-AbfrageObjectContext Compiled Query 10991099 3868262438682624
EF5EF5 ObjectContext (LINQ-Abfrage)ObjectContext Linq Query 11521152 3817881638178816
EF5EF5 Dbcontext LINQ-Abfrage keine NachverfolgungDbContext Linq Query No Tracking 12081208 4180377641803776
EF5EF5 Dbcontext-SQL-Abfrage für dbsetDbContext Sql Query on DbSet 14141414 3798220837982208
EF5EF5 Dbcontext-LINQ-AbfrageDbContext Linq Query 15741574 4173824041738240
EF6EF6 ObjectContext-Entitäts BefehlObjectContext Entity Command 480480 4724736047247360
EF6EF6 ObjectContext-Speicher AbfrageObjectContext Store Query 493493 4673945646739456
EF6EF6 Dbcontext-SQL-Abfrage für DatenbankDbContext Sql Query on Database 614614 4160716841607168
EF6EF6 ObjectContext LINQ-Abfrage keine NachverfolgungObjectContext Linq Query No Tracking 684684 4633395246333952
EF6EF6 ObjectContext Entity SQL mit Objekt AbfrageObjectContext Entity Sql using Object Query 767767 4886528048865280
EF6EF6 Kompilierte ObjectContext-AbfrageObjectContext Compiled Query 788788 4846796848467968
EF6EF6 Dbcontext LINQ-Abfrage keine NachverfolgungDbContext Linq Query No Tracking 878878 4755456047554560
EF6EF6 ObjectContext (LINQ-Abfrage)ObjectContext Linq Query 953953 4763238447632384
EF6EF6 Dbcontext-SQL-Abfrage für dbsetDbContext Sql Query on DbSet 10231023 4199219241992192
EF6EF6 Dbcontext-LINQ-AbfrageDbContext Linq Query 12901290 4752998447529984

EF5 warm Query 1000 Iterationen

EF6 warm Query 1000 Iterationen

Hinweis

Aus Gründen der Vollständigkeit enthalten wir eine Variation, bei der wir eine Entity SQL Abfrage für einen EntityCommand ausführen.For completeness, we included a variation where we execute an Entity SQL query on an EntityCommand. Da die Ergebnisse für solche Abfragen jedoch nicht materialisiert werden, ist der Vergleich nicht notwendigerweise "Äpfel-zu-Äpfel".However, because results are not materialized for such queries, the comparison isn't necessarily apples-to-apples. Der Test beinhaltet eine genaue Näherung, um den Vergleich zu gestalten.The test includes a close approximation to materializing to try making the comparison fairer.

In diesem End-to-End-Fall Entity Framework 6 Entity Framework 5 aufgrund von Leistungsverbesserungen, die an mehreren Teilen des Stapels vorgenommen werden, einschließlich einer wesentlich leichteren dbcontext-Initialisierung und schnelleren MetadataCollection T-suchen < > .In this end-to-end case, Entity Framework 6 outperforms Entity Framework 5 due to performance improvements made on several parts of the stack, including a much lighter DbContext initialization and faster MetadataCollection<T> lookups.

7 Überlegungen zur Entwurfszeit Leistung7 Design time performance considerations

7,1 Vererbungs Strategien7.1       Inheritance Strategies

Ein weiterer Leistungs Aspekt bei der Verwendung von Entity Framework ist die von Ihnen verwendete Vererbungs Strategie.Another performance consideration when using Entity Framework is the inheritance strategy you use. Entity Framework unterstützt 3 grundlegende Arten von Vererbung und deren Kombinationen:Entity Framework supports 3 basic types of inheritance and their combinations:

  • Tabelle pro Hierarchie (TPH) – wobei jeder Vererbungs Satz einer Tabelle mit einer diskriminatorspalte zugeordnet wird, um anzugeben, welcher bestimmte Typ in der Hierarchie in der Zeile dargestellt wird.Table per Hierarchy (TPH) – where each inheritance set maps to a table with a discriminator column to indicate which particular type in the hierarchy is being represented in the row.
  • Tabelle pro Typ (TPT) – wobei jeder Typ über eine eigene Tabelle in der Datenbank verfügt. in den untergeordneten Tabellen sind nur die Spalten definiert, die in der übergeordneten Tabelle enthalten sind.Table per Type (TPT) – where each type has its own table in the database; the child tables only define the columns that the parent table doesn’t contain.
  • Tabelle pro Klasse (TPC) – wobei jeder Typ über eine eigene vollständige Tabelle in der Datenbank verfügt. die untergeordneten Tabellen definieren alle Ihre Felder, einschließlich derjenigen, die in übergeordneten Typen definiert sind.Table per Class (TPC) – where each type has its own full table in the database; the child tables define all their fields, including those defined in parent types.

Wenn in Ihrem Modell die TPT-Vererbung verwendet wird, sind die generierten Abfragen komplexer als diejenigen, die mit den anderen Vererbungs Strategien generiert werden, was zu längeren Ausführungszeiten im Speicher führen kann.If your model uses TPT inheritance, the queries which are generated will be more complex than those that are generated with the other inheritance strategies, which may result on longer execution times on the store.Es dauert in der Regel länger, bis Abfragen über ein TPT-Modell generiert werden und die resultierenden Objekte materialisiert werden.  It will generally take longer to generate queries over a TPT model, and to materialize the resulting objects.

Weitere Informationen finden Sie Entity Framework im MSDN-Blogbeitrag unter "Überlegungen zur Leistung bei der Verwendung der TPT-Vererbung (Tabelle pro Typ)": <https://docs.microsoft.com/archive/blogs/adonet/performance-considerations-when-using-tpt-table-per-type-inheritance-in-the-entity-framework> .See the "Performance Considerations when using TPT (Table per Type) Inheritance in the Entity Framework" MSDN blog post: <https://docs.microsoft.com/archive/blogs/adonet/performance-considerations-when-using-tpt-table-per-type-inheritance-in-the-entity-framework>.

7.1.1 vermeiden von TPT in Model First oder Code First Anwendungen7.1.1       Avoiding TPT in Model First or Code First applications

Wenn Sie ein Modell über eine vorhandene Datenbank mit einem TPT-Schema erstellen, haben Sie nicht viele Optionen.When you create a model over an existing database that has a TPT schema, you don't have many options. Wenn Sie jedoch eine Anwendung mit Model First oder Code First erstellen, sollten Sie die TPT-Vererbung für Leistungsprobleme vermeiden.But when creating an application using Model First or Code First, you should avoid TPT inheritance for performance concerns.

Wenn Sie Model First im Entity Designer-Assistenten verwenden, erhalten Sie die TPT für jede Vererbung in Ihrem Modell.When you use Model First in the Entity Designer Wizard, you will get TPT for any inheritance in your model. Wenn Sie mit Model First zu einer TPH-Vererbungs Strategie wechseln möchten, können Sie das "Entity Designer Database Generation Power Pack" verwenden, das in der Visual Studio Gallery () verfügbar ist <http://visualstudiogallery.msdn.microsoft.com/df3541c3-d833-4b65-b942-989e7ec74c87/> .If you want to switch to a TPH inheritance strategy with Model First, you can use the "Entity Designer Database Generation Power Pack" available from the Visual Studio Gallery ( <http://visualstudiogallery.msdn.microsoft.com/df3541c3-d833-4b65-b942-989e7ec74c87/>).

Wenn Sie Code First verwenden, um die Zuordnung eines Modells mit Vererbung zu konfigurieren, verwendet EF standardmäßig TPH. Daher werden alle Entitäten in der Vererbungs Hierarchie derselben Tabelle zugeordnet.When using Code First to configure the mapping of a model with inheritance, EF will use TPH by default, therefore all entities in the inheritance hierarchy will be mapped to the same table. Weitere Informationen finden Sie im MSDN Magazine () im Abschnitt "Mapping with the fließend API" des Themas "Code First in Entity Framework 4.1" http://msdn.microsoft.com/magazine/hh126815.aspx .See the "Mapping with the Fluent API" section of the "Code First in Entity Framework4.1" article in MSDN Magazine ( http://msdn.microsoft.com/magazine/hh126815.aspx) for more details.

7,2 Upgrade von EF4 zur Verbesserung der Modell Generierungs Zeit7.2       Upgrading from EF4 to improve model generation time

Eine SQL Server spezifische Verbesserung des Algorithmus, der die Speicherschicht (SSDL) des Modells generiert, ist in Entity Framework 5 und 6 verfügbar und als Update für Entity Framework 4, wenn Visual Studio 2010 SP1 installiert ist.A SQL Server-specific improvement to the algorithm that generates the store-layer (SSDL) of the model is available in Entity Framework 5 and 6, and as an update to Entity Framework 4 when Visual Studio 2010 SP1 is installed. Die folgenden Testergebnisse veranschaulichen die Verbesserung beim Erstellen eines sehr großen Modells, in diesem Fall das Navision-Modell.The following test results demonstrate the improvement when generating a very big model, in this case the Navision model. Weitere Informationen hierzu finden Sie in Anhang C.See Appendix C for more details about it.

Das Modell enthält 1005 Entitätenmengen und 4227 Zuordnungs Sätze.The model contains 1005 entity sets and 4227 association sets.

KonfigurationConfiguration Aufschlüsselung der verbrauchten ZeitBreakdown of time consumed
Visual Studio 2010, Entity Framework 4Visual Studio 2010, Entity Framework 4 SSDL-Generierung: 2 Std. 27 min.SSDL Generation: 2 hr 27 min
Mapping-Generierung: 1 SekundeMapping Generation: 1 second
CSDL-Generierung: 1 SekundeCSDL Generation: 1 second
Objectlayer-Generierung: 1 SekundeObjectLayer Generation: 1 second
Ansichts Generierung: 2 Std. 14 min.View Generation: 2 h 14 min
Visual Studio 2010 SP1, Entity Framework 4Visual Studio 2010 SP1, Entity Framework 4 SSDL-Generierung: 1 SekundeSSDL Generation: 1 second
Mapping-Generierung: 1 SekundeMapping Generation: 1 second
CSDL-Generierung: 1 SekundeCSDL Generation: 1 second
Objectlayer-Generierung: 1 SekundeObjectLayer Generation: 1 second
Sicht Generierung: 1 Stunde 53 min.View Generation: 1 hr 53 min
Visual Studio 2013, Entity Framework 5Visual Studio 2013, Entity Framework 5 SSDL-Generierung: 1 SekundeSSDL Generation: 1 second
Mapping-Generierung: 1 SekundeMapping Generation: 1 second
CSDL-Generierung: 1 SekundeCSDL Generation: 1 second
Objectlayer-Generierung: 1 SekundeObjectLayer Generation: 1 second
Ansichts Generierung: 65 MinutenView Generation: 65 minutes
Visual Studio 2013, Entity Framework 6Visual Studio 2013, Entity Framework 6 SSDL-Generierung: 1 SekundeSSDL Generation: 1 second
Mapping-Generierung: 1 SekundeMapping Generation: 1 second
CSDL-Generierung: 1 SekundeCSDL Generation: 1 second
Objectlayer-Generierung: 1 SekundeObjectLayer Generation: 1 second
Sicht Generierung: 28 Sekunden.View Generation: 28 seconds.

Beachten Sie, dass die Auslastung beim Erzeugen der SSDL fast vollständig für den SQL Server aufgewendet wird, während der Client Entwicklungs Computer im Leerlauf darauf wartet, dass Ergebnisse vom Server zurückgegeben werden.It's worth noting that when generating the SSDL, the load is almost entirely spent on the SQL Server, while the client development machine is waiting idle for results to come back from the server. DBAs sollten diese Verbesserung besonders schätzen.DBAs should particularly appreciate this improvement. Es ist auch erwähnenswert, dass im Wesentlichen die Gesamtkosten für die Modell Generierung in der Ansichts Generierung erfolgt sind.It's also worth noting that essentially the entire cost of model generation takes place in View Generation now.

7,3 Aufteilen von großen Modellen mit Database First und Model First7.3       Splitting Large Models with Database First and Model First

Wenn die Modell Größe zunimmt, wird die Designer Oberfläche überladen und ist schwierig zu verwenden.As model size increases, the designer surface becomes cluttered and difficult to use. In der Regel wird ein Modell mit mehr als 300 Entitäten als zu groß betrachtet, um den Designer effektiv zu verwenden.We typically consider a model with more than 300 entities to be too large to effectively use the designer. Im folgenden Blogbeitrag werden verschiedene Optionen zum Aufteilen großer Modelle beschrieben: <https://docs.microsoft.com/archive/blogs/adonet/working-with-large-models-in-entity-framework-part-2> .The following blog post describes several options for splitting large models: <https://docs.microsoft.com/archive/blogs/adonet/working-with-large-models-in-entity-framework-part-2>.

Der Beitrag wurde für die erste Version von Entity Framework geschrieben, die Schritte sind jedoch weiterhin anwendbar.The post was written for the first version of Entity Framework, but the steps still apply.

7,4 Überlegungen zur Leistung mit dem Entitäts Datenquellen-Steuerelement7.4       Performance considerations with the Entity Data Source Control

Es wurden Fälle bei Multithread-Leistungs-und Belastungstests erkannt, bei denen sich die Leistung einer Webanwendung mit dem EntityDataSource-Steuerelement erheblich verschlechtert.We've seen cases in multi-threaded performance and stress tests where the performance of a web application using the EntityDataSource Control deteriorates significantly. Der Grund dafür ist, dass EntityDataSource wiederholt MetadataWorkspace. LoadFromAssembly für die Assemblys aufruft, auf die die Webanwendung verweist, um die Typen zu ermitteln, die als Entitäten verwendet werden sollen.The underlying cause is that the EntityDataSource repeatedly calls MetadataWorkspace.LoadFromAssembly on the assemblies referenced by the Web application to discover the types to be used as entities.

Die Lösung besteht darin, den contexttyid-Wert der EntityDataSource auf den Typnamen der abgeleiteten ObjectContext-Klasse festzulegen.The solution is to set the ContextTypeName of the EntityDataSource to the type name of your derived ObjectContext class. Dadurch wird der Mechanismus deaktiviert, der alle referenzierten Assemblys für Entitäts Typen scannt.This turns off the mechanism that scans all referenced assemblies for entity types.

Wenn Sie das Feld "contexttytzame" festlegen, wird auch ein funktionales Problem vermieden, bei dem die EntityDataSource in .NET 4,0 eine ReflectionTypeLoadException auslöst, wenn ein Typ nicht über Reflektion aus einer Assembly geladen werden kann.Setting the ContextTypeName field also prevents a functional problem where the EntityDataSource in .NET 4.0 throws a ReflectionTypeLoadException when it can't load a type from an assembly via reflection. Dieses Problem wurde in .NET 4,5 behoben.This issue has been fixed in .NET 4.5.

7,5 poco-Entitäten und Änderungs nach Verfolgungs Proxys7.5       POCO entities and change tracking proxies

Entity Framework ermöglicht es Ihnen, benutzerdefinierte Daten Klassen in Verbindung mit dem Datenmodell zu verwenden, ohne Änderungen an den Daten Klassen vorzunehmen.Entity Framework enables you to use custom data classes together with your data model without making any modifications to the data classes themselves. Dies bedeutet, dass Sie POCO-Objekte (Plain-old CLR objects), z. B. vorhandene Domänenobjekte, mit dem Datenmodell verwenden können.This means that you can use "plain-old" CLR objects (POCO), such as existing domain objects, with your data model. Diese poco-Daten Klassen (auch als Persistenz ignorierende Objekte bezeichnet), die Entitäten zugeordnet werden, die in einem Datenmodell definiert sind, unterstützen die meisten der gleichen Abfrage-, Einfüge-, Aktualisierungs-und Lösch Verhalten wie Entitäts Typen, die von den Entity Data Model Tools generiert werden.These POCO data classes (also known as persistence-ignorant objects), which are mapped to entities that are defined in a data model, support most of the same query, insert, update, and delete behaviors as entity types that are generated by the Entity Data Model tools.

Entity Framework können auch Proxy Klassen erstellen, die von ihren poco-Typen abgeleitet werden, die verwendet werden, um Funktionen wie Lazy Loading und die automatische Änderungs Nachverfolgung für poco-Entitäten zu aktivieren.Entity Framework can also create proxy classes derived from your POCO types, which are used when you want to enable features such as lazy loading and automatic change tracking on POCO entities. Die poco-Klassen müssen bestimmte Anforderungen erfüllen, damit Entity Framework Proxys verwenden können, wie hier beschrieben: http://msdn.microsoft.com/library/dd468057.aspx .Your POCO classes must meet certain requirements to allow Entity Framework to use proxies, as described here: http://msdn.microsoft.com/library/dd468057.aspx.

Proxynachverfolgungsproxys benachrichtigen den Objekt Zustands-Manager immer dann, wenn für eine der Eigenschaften der Entitäten der Wert geändert wird, sodass Entity Framework den tatsächlichen Zustand ihrer Entitäten ständig kennt.Chance tracking proxies will notify the object state manager each time any of the properties of your entities has its value changed, so Entity Framework knows the actual state of your entities all the time. Dies erfolgt durch Hinzufügen von Benachrichtigungs Ereignissen zum Text der Setter-Methoden der Eigenschaften, und der Objekt Zustands-Manager verarbeitet solche Ereignisse.This is done by adding notification events to the body of the setter methods of your properties, and having the object state manager processing such events. Beachten Sie, dass das Erstellen einer Proxy Entität in der Regel teurer ist als das Erstellen einer nicht-Proxy-poco-Entität aufgrund des zusätzlichen Satzes von Ereignissen, die von Entity Framework erstellt werden.Note that creating a proxy entity will typically be more expensive than creating a non-proxy POCO entity due to the added set of events created by Entity Framework.

Wenn eine poco-Entität keinen Änderungs nach Verfolgungs Proxy aufweist, werden Änderungen durch Vergleichen des Inhalts ihrer Entitäten mit einer Kopie eines vorherigen gespeicherten Zustands gefunden.When a POCO entity does not have a change tracking proxy, changes are found by comparing the contents of your entities against a copy of a previous saved state. Dieser umfassende Vergleich wird ein langwieriger Prozess, wenn Sie viele Entitäten in ihrem Kontext haben oder wenn Ihre Entitäten über eine sehr große Anzahl von Eigenschaften verfügen, auch wenn Sie sich seit dem letzten Vergleich nicht geändert haben.This deep comparison will become a lengthy process when you have many entities in your context, or when your entities have a very large amount of properties, even if none of them changed since the last comparison took place.

Zusammenfassung: beim Erstellen des Änderungs nach Verfolgungs Proxys wird eine Leistungs Beeinträchtigung erzielt, aber die Änderungs Nachverfolgung hilft Ihnen, den Änderungs Erkennungsprozess zu beschleunigen, wenn die Entitäten viele Eigenschaften haben oder wenn Sie über viele Entitäten in Ihrem Modell verfügen.In summary: you’ll pay a performance hit when creating the change tracking proxy, but change tracking will help you speed up the change detection process when your entities have many properties or when you have many entities in your model. Für Entitäten mit einer kleinen Anzahl von Eigenschaften, bei denen die Menge an Entitäten nicht zu stark zunimmt, sind Änderungs nach Verfolgungs Proxys möglicherweise nicht von großem Nutzen.For entities with a small number of properties where the amount of entities doesn’t grow too much, having change tracking proxies may not be of much benefit.

8,1 Lazy Load im Vergleich zum unverwollten laden8.1 Lazy Loading vs. Eager Loading

Entity Framework bietet verschiedene Möglichkeiten, um die Entitäten zu laden, die mit der Ziel Entität verknüpft sind.Entity Framework offers several different ways to load the entities that are related to your target entity. Wenn Sie z. b. Produkte Abfragen, gibt es verschiedene Möglichkeiten, wie die zugehörigen Bestellungen in den Objekt Zustands-Manager geladen werden.For example, when you query for Products, there are different ways that the related Orders will be loaded into the Object State Manager. Aus Sicht der Leistung ist es am wichtigsten, beim Laden von verknüpften Entitäten zu beachten, ob Lazy Load oder das unverzügliches Laden verwendet werden soll.From a performance standpoint, the biggest question to consider when loading related entities will be whether to use Lazy Loading or Eager Loading.

Wenn Sie das unverzügliches Laden verwenden, werden die zugehörigen Entitäten zusammen mit der Ziel Entitätenmenge geladen.When using Eager Loading, the related entities are loaded along with your target entity set. Sie verwenden eine include-Anweisung in der Abfrage, um anzugeben, welche verknüpften Entitäten Sie einfügen möchten.You use an Include statement in your query to indicate which related entities you want to bring in.

Wenn Lazy Load verwendet wird, führt die anfängliche Abfrage nur die Ziel Entitätenmenge ein.When using Lazy Loading, your initial query only brings in the target entity set. Wenn Sie jedoch auf eine Navigations Eigenschaft zugreifen, wird eine andere Abfrage für den Speicher ausgegeben, um die zugehörige Entität zu laden.But whenever you access a navigation property, another query is issued against the store to load the related entity.

Nachdem eine Entität geladen wurde, laden alle weiteren Abfragen für die Entität Sie direkt aus dem Objektstatus-Manager, unabhängig davon, ob Sie Lazy Loading oder Eager Loading verwenden.Once an entity has been loaded, any further queries for the entity will load it directly from the Object State Manager, whether you are using lazy loading or eager loading.

8,2 auswählen zwischen Lazy Load und unverzüglichem laden8.2 How to choose between Lazy Loading and Eager Loading

Wichtig ist, dass Sie den Unterschied zwischen Lazy Load und Lazy Load verstehen, damit Sie die richtige Wahl für Ihre Anwendung treffen können.The important thing is that you understand the difference between Lazy Loading and Eager Loading so that you can make the correct choice for your application. Dies hilft Ihnen, den Kompromiss zwischen mehreren Anforderungen an die Datenbank und einer einzelnen Anforderung, die möglicherweise eine große Nutzlast enthält, auszuwerten.This will help you evaluate the tradeoff between multiple requests against the database versus a single request that may contain a large payload. Es kann sinnvoll sein, Eager Loading in einigen Teilen Ihrer Anwendung zu verwenden und in anderen Teilen Lazy Loading.It may be appropriate to use eager loading in some parts of your application and lazy loading in other parts.

Angenommen, Sie möchten die Kunden, die im Vereinigten Königreich leben, und deren Bestell Anzahl Abfragen.As an example of what's happening under the hood, suppose you want to query for the customers who live in the UK and their order count.

Verwenden des unverwolltenUsing Eager Loading

using (NorthwindEntities context = new NorthwindEntities())
{
    var ukCustomers = context.Customers.Include(c => c.Orders).Where(c => c.Address.Country == "UK");
    var chosenCustomer = AskUserToPickCustomer(ukCustomers);
    Console.WriteLine("Customer Id: {0} has {1} orders", customer.CustomerID, customer.Orders.Count);
}

Verwenden von Lazy LoadUsing Lazy Loading

using (NorthwindEntities context = new NorthwindEntities())
{
    context.ContextOptions.LazyLoadingEnabled = true;

    //Notice that the Include method call is missing in the query
    var ukCustomers = context.Customers.Where(c => c.Address.Country == "UK");

    var chosenCustomer = AskUserToPickCustomer(ukCustomers);
    Console.WriteLine("Customer Id: {0} has {1} orders", customer.CustomerID, customer.Orders.Count);
}

Wenn Sie Eager Loading verwenden, geben Sie eine einzelne Abfrage aus, mit der alle Kunden und alle Bestellungen zurückgegeben werden.When using eager loading, you'll issue a single query that returns all customers and all orders. Der Store-Befehl sieht wie folgt aus:The store command looks like:

SELECT
[Project1].[C1] AS [C1],
[Project1].[CustomerID] AS [CustomerID],
[Project1].[CompanyName] AS [CompanyName],
[Project1].[ContactName] AS [ContactName],
[Project1].[ContactTitle] AS [ContactTitle],
[Project1].[Address] AS [Address],
[Project1].[City] AS [City],
[Project1].[Region] AS [Region],
[Project1].[PostalCode] AS [PostalCode],
[Project1].[Country] AS [Country],
[Project1].[Phone] AS [Phone],
[Project1].[Fax] AS [Fax],
[Project1].[C2] AS [C2],
[Project1].[OrderID] AS [OrderID],
[Project1].[CustomerID1] AS [CustomerID1],
[Project1].[EmployeeID] AS [EmployeeID],
[Project1].[OrderDate] AS [OrderDate],
[Project1].[RequiredDate] AS [RequiredDate],
[Project1].[ShippedDate] AS [ShippedDate],
[Project1].[ShipVia] AS [ShipVia],
[Project1].[Freight] AS [Freight],
[Project1].[ShipName] AS [ShipName],
[Project1].[ShipAddress] AS [ShipAddress],
[Project1].[ShipCity] AS [ShipCity],
[Project1].[ShipRegion] AS [ShipRegion],
[Project1].[ShipPostalCode] AS [ShipPostalCode],
[Project1].[ShipCountry] AS [ShipCountry]
FROM ( SELECT
      [Extent1].[CustomerID] AS [CustomerID],
       [Extent1].[CompanyName] AS [CompanyName],
       [Extent1].[ContactName] AS [ContactName],
       [Extent1].[ContactTitle] AS [ContactTitle],
       [Extent1].[Address] AS [Address],
       [Extent1].[City] AS [City],
       [Extent1].[Region] AS [Region],
       [Extent1].[PostalCode] AS [PostalCode],
       [Extent1].[Country] AS [Country],
       [Extent1].[Phone] AS [Phone],
       [Extent1].[Fax] AS [Fax],
      1 AS [C1],
       [Extent2].[OrderID] AS [OrderID],
       [Extent2].[CustomerID] AS [CustomerID1],
       [Extent2].[EmployeeID] AS [EmployeeID],
       [Extent2].[OrderDate] AS [OrderDate],
       [Extent2].[RequiredDate] AS [RequiredDate],
       [Extent2].[ShippedDate] AS [ShippedDate],
       [Extent2].[ShipVia] AS [ShipVia],
       [Extent2].[Freight] AS [Freight],
       [Extent2].[ShipName] AS [ShipName],
       [Extent2].[ShipAddress] AS [ShipAddress],
       [Extent2].[ShipCity] AS [ShipCity],
       [Extent2].[ShipRegion] AS [ShipRegion],
       [Extent2].[ShipPostalCode] AS [ShipPostalCode],
       [Extent2].[ShipCountry] AS [ShipCountry],
      CASE WHEN ([Extent2].[OrderID] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C2]
      FROM  [dbo].[Customers] AS [Extent1]
      LEFT OUTER JOIN [dbo].[Orders] AS [Extent2] ON [Extent1].[CustomerID] = [Extent2].[CustomerID]
      WHERE N'UK' = [Extent1].[Country]
)  AS [Project1]
ORDER BY [Project1].[CustomerID] ASC, [Project1].[C2] ASC

Wenn Sie Lazy Loading verwenden, geben Sie zunächst die folgende Abfrage aus:When using lazy loading, you'll issue the following query initially:

SELECT
[Extent1].[CustomerID] AS [CustomerID],
[Extent1].[CompanyName] AS [CompanyName],
[Extent1].[ContactName] AS [ContactName],
[Extent1].[ContactTitle] AS [ContactTitle],
[Extent1].[Address] AS [Address],
[Extent1].[City] AS [City],
[Extent1].[Region] AS [Region],
[Extent1].[PostalCode] AS [PostalCode],
[Extent1].[Country] AS [Country],
[Extent1].[Phone] AS [Phone],
[Extent1].[Fax] AS [Fax]
FROM [dbo].[Customers] AS [Extent1]
WHERE N'UK' = [Extent1].[Country]

Und jedes Mal, wenn Sie auf die Orders-Navigations Eigenschaft eines Kunden zugreifen, wird eine andere Abfrage wie die folgende für den Speicher ausgegeben:And each time you access the Orders navigation property of a customer another query like the following is issued against the store:

exec sp_executesql N'SELECT
[Extent1].[OrderID] AS [OrderID],
[Extent1].[CustomerID] AS [CustomerID],
[Extent1].[EmployeeID] AS [EmployeeID],
[Extent1].[OrderDate] AS [OrderDate],
[Extent1].[RequiredDate] AS [RequiredDate],
[Extent1].[ShippedDate] AS [ShippedDate],
[Extent1].[ShipVia] AS [ShipVia],
[Extent1].[Freight] AS [Freight],
[Extent1].[ShipName] AS [ShipName],
[Extent1].[ShipAddress] AS [ShipAddress],
[Extent1].[ShipCity] AS [ShipCity],
[Extent1].[ShipRegion] AS [ShipRegion],
[Extent1].[ShipPostalCode] AS [ShipPostalCode],
[Extent1].[ShipCountry] AS [ShipCountry]
FROM [dbo].[Orders] AS [Extent1]
WHERE [Extent1].[CustomerID] = @EntityKeyValue1',N'@EntityKeyValue1 nchar(5)',@EntityKeyValue1=N'AROUT'

Weitere Informationen finden Sie unter Laden verwandter Objekte.For more information, see the Loading Related Objects.

8.2.1 Lazy Load im Vergleich zu unverzüglichem laden Cheat Sheet8.2.1 Lazy Loading versus Eager Loading cheat sheet

Es gibt keine Möglichkeit, Eager Loading im Vergleich zu Lazy Loading zu wählen.There’s no such thing as a one-size-fits-all to choosing eager loading versus lazy loading. Versuchen Sie zunächst, die Unterschiede zwischen beiden Strategien zu verstehen, damit Sie eine fundierte Entscheidung treffen können. Beachten Sie auch, wenn Ihr Code in eines der folgenden Szenarien passt:Try first to understand the differences between both strategies so you can do a well informed decision; also, consider if your code fits to any of the following scenarios:

SzenarioScenario Unsere EmpfehlungOur Suggestion
Benötigen Sie Zugriff auf viele Navigations Eigenschaften aus den abgerufenen Entitäten?Do you need to access many navigation properties from the fetched entities? Nein , beide Optionen werden wahrscheinlich funktionieren.No - Both options will probably do. Wenn die von der Abfrage abzurufende Nutzlast jedoch nicht zu groß ist, können Sie Leistungsvorteile erzielen, indem Sie das unverzügliches Laden verwenden, da dafür weniger Netzwerkroundtrips erforderlich sind, um Ihre Objekte zu materialisieren.However, if the payload your query is bringing is not too big, you may experience performance benefits by using Eager loading as it’ll require less network round trips to materialize your objects.

Ja : Wenn Sie von den Entitäten aus auf viele Navigations Eigenschaften zugreifen müssen, verwenden Sie mehrere include-Anweisungen in der Abfrage mit unverzüglichem laden.Yes - If you need to access many navigation properties from the entities, you’d do that by using multiple include statements in your query with Eager loading. Je mehr Entitäten Sie einbeziehen, desto größer ist die Nutzlast, die von der Abfrage zurückgegeben wird.The more entities you include, the bigger the payload your query will return. Wenn Sie drei oder mehr Entitäten in die Abfrage einschließen, sollten Sie in Erwägung gezogen, zu Lazy Load zu wechseln.Once you include three or more entities into your query, consider switching to Lazy loading.
Wissen Sie genau, welche Daten zur Laufzeit benötigt werden?Do you know exactly what data will be needed at run time? Kein Lazy Load ist für Sie besser geeignet.No - Lazy loading will be better for you. Andernfalls können Sie Daten Abfragen, die Sie nicht benötigen.Otherwise, you may end up querying for data that you will not need.

" Ja " ist wahrscheinlich die beste Lösung. Dadurch wird das Laden ganzer Mengen beschleunigt.Yes - Eager loading is probably your best bet; it will help loading entire sets faster. Wenn die Abfrage das Abrufen einer sehr großen Datenmenge erfordert und diese zu langsam wird, versuchen Sie stattdessen Lazy Load.If your query requires fetching a very large amount of data, and this becomes too slow, then try Lazy loading instead.
Wird Ihr Code weit von der Datenbank ausgeführt?Is your code executing far from your database? (größere Netzwerk Latenz)(increased network latency) Nein : Wenn die Netzwerk Latenz kein Problem ist, kann der Code durch die Verwendung von Lazy Load vereinfacht werden.No - When the network latency is not an issue, using Lazy loading may simplify your code. Denken Sie daran, dass sich die Topologie Ihrer Anwendung ändern kann, und nehmen Sie daher keine Daten Bank Nähe.Remember that the topology of your application may change, so don’t take database proximity for granted.

Ja : Wenn es sich bei dem Netzwerk um ein Problem handelt, können Sie nur entscheiden, was für Ihr Szenario besser geeignet ist.Yes - When the network is a problem, only you can decide what fits better for your scenario. Üblicherweise ist das vorzeitige Laden besser, da es weniger Roundtrips erfordert.Typically Eager loading will be better because it requires fewer round trips.

8.2.2 Leistungsprobleme mit mehreren includes8.2.2       Performance concerns with multiple Includes

Wenn wir Leistungs Fragen hören, die Probleme mit der Serverantwort Zeit betreffen, ist die Ursache des Problems häufig Abfragen mit mehreren include-Anweisungen.When we hear performance questions that involve server response time problems, the source of the issue is frequently queries with multiple Include statements. Das Einschließen von verknüpften Entitäten in eine Abfrage ist zwar leistungsstark, aber es ist wichtig zu verstehen, was im Zusammenhang geschieht.While including related entities in a query is powerful, it's important to understand what's happening under the covers.

Es dauert relativ lange, bis eine Abfrage mit mehreren include-Anweisungen den internen Plan Compiler durchläuft, um den Store-Befehl zu erhalten.It takes a relatively long time for a query with multiple Include statements in it to go through our internal plan compiler to produce the store command. Der Großteil dieser Zeit wird beim Versuch aufgewendet, die resultierende Abfrage zu optimieren.The majority of this time is spent trying to optimize the resulting query. Der generierte Speicher Befehl enthält abhängig von ihrer Zuordnung einen äußeren Join oder eine Union für jede include-Anweisung.The generated store command will contain an Outer Join or Union for each Include, depending on your mapping. Abfragen wie diese führen zu großen verbundenen Diagrammen aus Ihrer Datenbank in einer einzelnen Nutzlast, wodurch alle Bandbreitenprobleme, insbesondere dann, wenn die Nutzlast viele Redundanz aufweist (z. b. Wenn mehrere Ebenen von include verwendet werden, zum Durchlaufen von Zuordnungen in der 1: n-Richtung verwendet werden).Queries like this will bring in large connected graphs from your database in a single payload, which will acerbate any bandwidth issues, especially when there is a lot of redundancy in the payload (for example, when multiple levels of Include are used to traverse associations in the one-to-many direction).

Sie können überprüfen, ob Ihre Abfragen übermäßig große Nutzlasten zurückgeben, indem Sie auf den zugrunde liegenden TQL für die Abfrage zugreifen, indem Sie "$ tracestring" verwenden und den Speicher Befehl in SQL Server Management Studio ausführen, um die Nutzlastgröße anzuzeigen.You can check for cases where your queries are returning excessively large payloads by accessing the underlying TSQL for the query by using ToTraceString and executing the store command in SQL Server Management Studio to see the payload size. In solchen Fällen können Sie versuchen, die Anzahl der include-Anweisungen in der Abfrage zu reduzieren, um nur die benötigten Daten zu erhalten.In such cases you can try to reduce the number of Include statements in your query to just bring in the data you need. Oder Sie können die Abfrage in eine kleinere Sequenz von Unterabfragen zerlegen, z. b.:Or you may be able to break your query into a smaller sequence of subqueries, for example:

Vor dem Abbrechen der Abfrage:Before breaking the query:

using (NorthwindEntities context = new NorthwindEntities())
{
    var customers = from c in context.Customers.Include(c => c.Orders)
                    where c.LastName.StartsWith(lastNameParameter)
                    select c;

    foreach (Customer customer in customers)
    {
        ...
    }
}

Nach dem Abbrechen der Abfrage:After breaking the query:

using (NorthwindEntities context = new NorthwindEntities())
{
    var orders = from o in context.Orders
                 where o.Customer.LastName.StartsWith(lastNameParameter)
                 select o;

    orders.Load();

    var customers = from c in context.Customers
                    where c.LastName.StartsWith(lastNameParameter)
                    select c;

    foreach (Customer customer in customers)
    {
        ...
    }
}

Dies funktioniert nur für nach verfolgte Abfragen, da wir die Möglichkeit nutzen, den Kontext für die automatische Durchführung der Identitäts Auflösung und Zuordnungs Korrektur zu verwenden.This will work only on tracked queries, as we are making use of the ability the context has to perform identity resolution and association fixup automatically.

Wie bei Lazy Loading sind die Nachteile mehr Abfragen für kleinere Nutzlasten.As with lazy loading, the tradeoff will be more queries for smaller payloads. Sie können auch Projektionen von einzelnen Eigenschaften verwenden, um explizit nur die benötigten Daten aus den einzelnen Entitäten auszuwählen. in diesem Fall werden jedoch keine Entitäten geladen, und Updates werden nicht unterstützt.You can also use projections of individual properties to explicitly select only the data you need from each entity, but you will not be loading entities in this case, and updates will not be supported.

8.2.3 Problem Umgehung, um Lazy Loading von Eigenschaften zu erhalten8.2.3 Workaround to get lazy loading of properties

Entity Framework Lazy Loading von skalaren oder komplexen Eigenschaften derzeit nicht unterstützt.Entity Framework currently doesn’t support lazy loading of scalar or complex properties. In Fällen, in denen Sie über eine Tabelle verfügen, die ein großes Objekt wie z. b. ein BLOB enthält, können Sie die Tabellen Aufteilung verwenden, um die großen Eigenschaften in einer separaten Entität voneinander zu trennen.However, in cases where you have a table that includes a large object such as a BLOB, you can use table splitting to separate the large properties into a separate entity. Angenommen, Sie verfügen über eine Tabelle "Product", die eine varbinary-Foto Spalte enthält.For example, suppose you have a Product table that includes a varbinary photo column. Wenn Sie in Ihren Abfragen nicht häufig auf diese Eigenschaft zugreifen müssen, können Sie die Tabellen Aufteilung verwenden, um nur die Teile der Entität zu verwenden, die Sie normalerweise benötigen.If you don't frequently need to access this property in your queries, you can use table splitting to bring in only the parts of the entity that you normally need. Die Entität, die das Produktfoto darstellt, wird nur geladen, wenn Sie Sie explizit benötigen.The entity representing the product photo will only be loaded when you explicitly need it.

Eine gute Ressource, die zeigt, wie Sie die Tabellen Aufteilung aktivieren, ist der Blogbeitrag "Tabellen Aufteilung in Entity Framework" von Gil Fink: <http://blogs.microsoft.co.il/blogs/gilf/archive/2009/10/13/table-splitting-in-entity-framework.aspx> .A good resource that shows how to enable table splitting is Gil Fink's "Table Splitting in Entity Framework" blog post: <http://blogs.microsoft.co.il/blogs/gilf/archive/2009/10/13/table-splitting-in-entity-framework.aspx>.

9 weitere Überlegungen9 Other considerations

9,1 Garbage Collection für Server9.1      Server Garbage Collection

Einige Benutzer können Ressourcenkonflikte feststellen, die die Parallelität einschränken, die Sie erwarten, wenn der Garbage Collector nicht ordnungsgemäß konfiguriert ist.Some users might experience resource contention that limits the parallelism they are expecting when the Garbage Collector is not properly configured. Wenn EF in einem Multithread-Szenario oder in einer Anwendung verwendet wird, die einem serverseitigen System ähnelt, stellen Sie sicher, dass die Garbage Collection auf dem Server aktiviert ist.Whenever EF is used in a multithreaded scenario, or in any application that resembles a server-side system, make sure to enable Server Garbage Collection. Dies erfolgt über eine einfache Einstellung in ihrer Anwendungs Konfigurationsdatei:This is done via a simple setting in your application config file:

<?xmlversion="1.0" encoding="utf-8" ?>
<configuration>
        <runtime>
               <gcServer enabled="true" />
        </runtime>
</configuration>

Dies sollte die Thread Konflikte verringern und den Durchsatz um bis zu 30% erhöhen.This should decrease your thread contention and increase your throughput by up to 30% in CPU saturated scenarios. In der Regel sollten Sie immer testen, wie sich Ihre Anwendung verhält, indem Sie die klassische Garbage Collection (die für Benutzeroberflächen-und Client seitige Szenarien besser optimiert ist) sowie die Garbage Collection auf dem Server verwenden.In general terms, you should always test how your application behaves using the classic Garbage Collection (which is better tuned for UI and client side scenarios) as well as the Server Garbage Collection.

9,2 autodetectchanges9.2      AutoDetectChanges

Wie bereits erwähnt, können Entity Framework Leistungsprobleme anzeigen, wenn der Objekt Cache über viele Entitäten verfügt.As mentioned earlier, Entity Framework might show performance issues when the object cache has many entities. Bestimmte Vorgänge, wie z. b. "Add", "Remove", "Find", "Entry" und "SaveChanges", fordern Aufrufe von "DetectChanges" an, die abhängig davon, wie groß der Objekt Cache geworden ist, viel CPUCertain operations, such as Add, Remove, Find, Entry and SaveChanges, trigger calls to DetectChanges which might consume a large amount of CPU based on how large the object cache has become. Der Grund hierfür ist, dass der Objekt Cache und der Objekt Zustands-Manager versuchen, bei jedem Vorgang, der in einem Kontext ausgeführt wird, so synchronisiert zu bleiben, dass die erzeugten Daten in einer Vielzahl von Szenarien korrekt sind.The reason for this is that the object cache and the object state manager try to stay as synchronized as possible on each operation performed to a context so that the produced data is guaranteed to be correct under a wide array of scenarios.

Im Allgemeinen empfiehlt es sich, die automatische Änderungs Erkennung Entity Framework für die gesamte Lebensdauer Ihrer Anwendung aktiviert zu lassen.It is generally a good practice to leave Entity Framework’s automatic change detection enabled for the entire life of your application. Wenn Ihr Szenario durch hohe CPU-Auslastung negativ beeinflusst wird und ihre Profile darauf hindeuten, dass es sich bei dem betäter um den Erkennungs Nachweis handelt, empfiehlt es sich, autodetectchanges im sensiblen Teil Ihres Codes vorübergehend zu deaktivieren:If your scenario is being negatively affected by high CPU usage and your profiles indicate that the culprit is the call to DetectChanges, consider temporarily turning off AutoDetectChanges in the sensitive portion of your code:

try
{
    context.Configuration.AutoDetectChangesEnabled = false;
    var product = context.Products.Find(productId);
    ...
}
finally
{
    context.Configuration.AutoDetectChangesEnabled = true;
}

Vor dem Ausschalten von autodetectchanges sollten Sie sich bewusst sein, dass dies dazu führen kann, dass Entity Framework die Fähigkeit verliert, bestimmte Informationen zu den Änderungen zu verfolgen, die für die Entitäten ausgeführt werden.Before turning off AutoDetectChanges, it’s good to understand that this might cause Entity Framework to lose its ability to track certain information about the changes that are taking place on the entities. Wenn Sie falsch behandelt werden, kann dies zu einer Daten Inkonsistenz Ihrer Anwendung führen.If handled incorrectly, this might cause data inconsistency on your application. Weitere Informationen zum Ausschalten von autodetectchanges finden Sie unter <http://blog.oneunicorn.com/2012/03/12/secrets-of-detectchanges-part-3-switching-off-automatic-detectchanges/> .For more information on turning off AutoDetectChanges, read <http://blog.oneunicorn.com/2012/03/12/secrets-of-detectchanges-part-3-switching-off-automatic-detectchanges/>.

9,3-Kontext pro Anforderung9.3      Context per request

Die Kontexte von Entity Framework sollen als kurzlebige Instanzen verwendet werden, um die optimale Leistung zu gewährleisten.Entity Framework’s contexts are meant to be used as short-lived instances in order to provide the most optimal performance experience. Es wird davon ausgegangen, dass Kontexte kurzlebig sind und verworfen werden. Daher wurden Sie so implementiert, dass Sie möglichst sehr einfach sind, und die Metadaten immer wieder überprüfen.Contexts are expected to be short lived and discarded, and as such have been implemented to be very lightweight and reutilize metadata whenever possible. In Webszenarien ist es wichtig, dies zu berücksichtigen und keinen Kontext für mehr als die Dauer einer einzelnen Anforderung zu erhalten.In web scenarios it’s important to keep this in mind and not have a context for more than the duration of a single request. Analog dazu sollte der Kontext in nicht-Webanwendungen verworfen werden, basierend auf dem Verständnis der verschiedenen Ebenen der Zwischenspeicherung in der Entity Framework.Similarly, in non-web scenarios, context should be discarded based on your understanding of the different levels of caching in the Entity Framework. Im Allgemeinen sollten Sie eine Kontext Instanz im gesamten Lebenszyklus der Anwendung sowie Kontexte pro Thread und statischen Kontexten vermeiden.Generally speaking, one should avoid having a context instance throughout the life of the application, as well as contexts per thread and static contexts.

9,4-Datenbank-NULL-Semantik9.4      Database null semantics

Standardmäßig wird von Entity Framework SQL-Code generiert, der über eine C- # null-Vergleichs Semantik verfügt.Entity Framework by default will generate SQL code that has C# null comparison semantics. Betrachten Sie die folgende Beispielabfrage:Consider the following example query:

            int? categoryId = 7;
            int? supplierId = 8;
            decimal? unitPrice = 0;
            short? unitsInStock = 100;
            short? unitsOnOrder = 20;
            short? reorderLevel = null;

            var q = from p incontext.Products
                    wherep.Category.CategoryName == "Beverages"
                          || (p.CategoryID == categoryId
                                || p.SupplierID == supplierId
                                || p.UnitPrice == unitPrice
                                || p.UnitsInStock == unitsInStock
                                || p.UnitsOnOrder == unitsOnOrder
                                || p.ReorderLevel == reorderLevel)
                    select p;

            var r = q.ToList();

In diesem Beispiel vergleichen wir eine Reihe von Variablen, die NULL-Werte zulassen, mit auf NULL festleg baren Eigenschaften in der Entität, z. b. SupplierID und UnitPrice.In this example, we’re comparing a number of nullable variables against nullable properties on the entity, such as SupplierID and UnitPrice. Der generierte SQL-Wert für diese Abfrage fragt, ob der Parameterwert mit dem Spaltenwert übereinstimmt oder ob der Parameter und die Spaltenwerte NULL sind.The generated SQL for this query will ask if the parameter value is the same as the column value, or if both the parameter and the column values are null. Dadurch wird die Art und Weise ausgeblendet, wie der Datenbankserver NULL-Werte verarbeitet und eine konsistente C-NULL-Funktion für # verschiedene Datenbankanbieter bereitstellt.This will hide the way the database server handles nulls and will provide a consistent C# null experience across different database vendors. Auf der anderen Seite ist der generierte Code etwas kompliziert und funktioniert möglicherweise nicht gut, wenn die Anzahl der Vergleiche in der WHERE-Anweisung der Abfrage zu einer hohen Zahl wächst.On the other hand, the generated code is a bit convoluted and may not perform well when the amount of comparisons in the where statement of the query grows to a large number.

Eine Möglichkeit, diese Situation zu behandeln, besteht in der Verwendung der NULL-Semantik für die Datenbank.One way to deal with this situation is by using database null semantics. Beachten Sie, dass dies möglicherweise anders als die Semantik des C-NULL-Werts verhält, # da Entity Framework nun einfacheres SQL generieren, das die Verarbeitung von NULL-Werten durch die Datenbank-Engine ermöglichtNote that this might potentially behave differently to the C# null semantics since now Entity Framework will generate simpler SQL that exposes the way the database engine handles null values. Die NULL-Semantik der Datenbank kann pro Kontext mit einer einzelnen Konfigurationszeile für die Kontext Konfiguration aktiviert werden:Database null semantics can be activated per-context with one single configuration line against the context configuration:

                context.Configuration.UseDatabaseNullSemantics = true;

Bei kleinen bis mittelgroßen Abfragen wird bei Verwendung der NULL-Semantik der Datenbank keine spürbare Leistungsverbesserung angezeigt, aber der Unterschied wird bei Abfragen mit einer großen Anzahl möglicher NULL-Vergleiche deutlicher.Small to medium sized queries will not display a perceptible performance improvement when using database null semantics, but the difference will become more noticeable on queries with a large number of potential null comparisons.

In der obigen Beispiel Abfrage war der Leistungsunterschied in einem in einer kontrollierten Umgebung laufenden Mikrobenchmark kleiner als 2%.In the example query above, the performance difference was less than 2% in a microbenchmark running in a controlled environment.

9,5 Async9.5      Async

In Entity Framework 6 wurde die Unterstützung von asynchronen Vorgängen bei Ausführung unter .NET 4,5 oder höher eingeführt.Entity Framework 6 introduced support of async operations when running on .NET 4.5 or later. In den meisten Fällen profitieren Anwendungen mit e/a-bezogenen Konflikten am meisten von der Verwendung von asynchronen Abfrage-und Speicher Vorgängen.For the most part, applications that have IO related contention will benefit the most from using asynchronous query and save operations. Wenn Ihre Anwendung von e/a-Konflikten nicht beeinträchtigt wird, wird die Verwendung von Async in den meisten Fällen synchron ausgeführt, und das Ergebnis wird in der gleichen Zeit wie ein synchroner Aufruf zurückgegeben, oder im schlimmsten Fall wird die Ausführung auf eine asynchrone Aufgabe verzögert, und der Abschluss des Szenarios wird zusätzlicher Zeitaufwand hinzugefügt.If your application does not suffer from IO contention, the use of async will, in the best cases, run synchronously and return the result in the same amount of time as a synchronous call, or in the worst case, simply defer execution to an asynchronous task and add extra time to the completion of your scenario.

Informationen dazu, wie die asynchrone Programmierung funktioniert, um zu entscheiden, ob die Leistung Ihrer Anwendung durch Async verbessert wird, finden Sie unter http://msdn.microsoft.com/library/hh191443.aspx .For information on how asynchronous programming work that will help you deciding if async will improve the performance of your application visit http://msdn.microsoft.com/library/hh191443.aspx. Weitere Informationen zur Verwendung von asynchronen Vorgängen auf Entity Framework finden Sie unter asynchrone Abfrage und Speicherung.For more information on the use of async operations on Entity Framework, see Async Query and Save.

9,6 ngen9.6      NGEN

Entity Framework 6 ist nicht in der Standardinstallation von .NET Framework enthalten.Entity Framework 6 does not come in the default installation of .NET framework. Daher sind die Entity Framework-Assemblys standardmäßig nicht ngen, was bedeutet, dass der gesamte Entity Framework Code denselben jitten Kosten wie jede andere MSIL-Assembly unterliegt.As such, the Entity Framework assemblies are not NGEN’d by default which means that all the Entity Framework code is subject to the same JIT’ing costs as any other MSIL assembly. Dies kann die F5-Umgebung bei der Entwicklung und dem Kaltstart der Anwendung in der Produktionsumgebung beeinträchtigen.This might degrade the F5 experience while developing and also the cold startup of your application in the production environments. Um die CPU-und Arbeitsspeicher Kosten zu verringern, empfiehlt es sich, die Entity Framework Abbilder nach Bedarf zu ngen.In order to reduce the CPU and memory costs of JIT’ing it is advisable to NGEN the Entity Framework images as appropriate. Weitere Informationen zum Verbessern der Startleistung von Entity Framework 6 mit Ngen finden Sie unter Verbessern der Startleistung mit Ngen.For more information on how to improve the startup performance of Entity Framework 6 with NGEN, see Improving Startup Performance with NGen.

9,7 Code First im Vergleich zu EDMX9.7      Code First versus EDMX

Entity Framework Gründe für das Problem mit dem Impedance-Konflikt zwischen der objektorientierten Programmierung und relationalen Datenbanken, indem eine Darstellung des konzeptionellen Modells (Objekte) im Speicher, das Speicher Schema (die Datenbank) und eine Zuordnung zwischen den beiden Datenbanken vorhanden sind.Entity Framework reasons about the impedance mismatch problem between object oriented programming and relational databases by having an in-memory representation of the conceptual model (the objects), the storage schema (the database) and a mapping between the two. Diese Metadaten werden als "Entity Data Model" oder "EDM" bezeichnet.This metadata is called an Entity Data Model, or EDM for short. Von diesem EDM leiten Entity Framework die Sichten zum Roundtrip von Daten aus den Objekten im Arbeitsspeicher in die Datenbank und zurück.From this EDM, Entity Framework will derive the views to roundtrip data from the objects in memory to the database and back.

Wenn Entity Framework mit einer EDMX-Datei verwendet wird, die das konzeptionelle Modell, das Speicher Schema und die Zuordnung formal angibt, muss in der Modell Lade Phase nur überprüft werden, ob das EDM korrekt ist (z. b. Stellen Sie sicher, dass keine Zuordnungen fehlen). generieren Sie dann die Sichten, und überprüfen Sie dann die Sichten, und lassen Sie diese Metadaten dann verwenden.When Entity Framework is used with an EDMX file that formally specifies the conceptual model, the storage schema, and the mapping, then the model loading stage only has to validate that the EDM is correct (for example, make sure that no mappings are missing), then generate the views, then validate the views and have this metadata ready for use. Nur dann kann eine Abfrage ausgeführt oder neue Daten im Datenspeicher gespeichert werden.Only then can a query be executed or new data be saved to the data store.

Der Code First Ansatz ist im Wesentlichen ein anspruchsvoller Entity Data Model Generator.The Code First approach is, at its heart, a sophisticated Entity Data Model generator. Der Entity Framework muss ein EDM aus dem bereitgestellten Code ergeben. Dies geschieht durch Analysieren der im Modell beteiligten Klassen, Anwenden von Konventionen und Konfigurieren des Modells über die fließende API.The Entity Framework has to produce an EDM from the provided code; it does so by analyzing the classes involved in the model, applying conventions and configuring the model via the Fluent API. Nachdem das EDM erstellt wurde, verhält sich der Entity Framework im Wesentlichen wie eine EDMX-Datei im Projekt.After the EDM is built, the Entity Framework essentially behaves the same way as it would had an EDMX file been present in the project. Daher wird durch die Erstellung des Modells aus Code First eine zusätzliche Komplexität hinzugefügt, die im Vergleich zu edmx zu einer langsameren Startzeit für die Entity Framework führt.Thus, building the model from Code First adds extra complexity that translates into a slower startup time for the Entity Framework when compared to having an EDMX. Die Kosten sind vollständig von der Größe und Komplexität des Modells abhängig, das erstellt wird.The cost is completely dependent on the size and complexity of the model that’s being built.

Wenn Sie sich für die Verwendung von edmx im Vergleich zu Code First entscheiden, ist es wichtig zu wissen, dass die durch Code First eingeführte Flexibilität die Kosten für die erstmalige Erstellung des Modells erhöht.When choosing to use EDMX versus Code First, it’s important to know that the flexibility introduced by Code First increases the cost of building the model for the first time. Wenn Ihre Anwendung die Kosten für diese erstmalige Auslastung widerrufen kann, ist Code First in der Regel die bevorzugte Methode.If your application can withstand the cost of this first-time load then typically Code First will be the preferred way to go.

10 Untersuchung der Leistung10 Investigating Performance

10,1 Verwenden von Visual Studio Profiler10.1 Using the Visual Studio Profiler

Wenn Sie Leistungsprobleme mit dem Entity Framework haben, können Sie einen Profiler wie den in Visual Studio integrierten Profiler verwenden, um zu sehen, wo Ihre Anwendung Ihre Zeit verbringt.If you are having performance issues with the Entity Framework, you can use a profiler like the one built into Visual Studio to see where your application is spending its time. Dies ist das Tool, das wir zum Generieren der Kreis Diagramme im Blogbeitrag "untersuchen der Leistung des ADO.NET Entity Framework-Part 1"-Blogbeitrags () verwendet haben, in dem <https://docs.microsoft.com/archive/blogs/adonet/exploring-the-performance-of-the-ado-net-entity-framework-part-1> gezeigt wird, wo Entity Framework seine Zeit während kalter und warmer Abfragen verbringt.This is the tool we used to generate the pie charts in the “Exploring the Performance of the ADO.NET Entity Framework - Part 1” blog post ( <https://docs.microsoft.com/archive/blogs/adonet/exploring-the-performance-of-the-ado-net-entity-framework-part-1>) that show where Entity Framework spends its time during cold and warm queries.

Der Blogbeitrag "Profilerstellung Entity Framework mit dem Visual Studio 2010 Profiler", der vom Kunden Beratungs Team für Daten und Modellierung verfasst wurde, zeigt ein reales Beispiel dafür, wie der Profiler zum Untersuchen eines Leistungs Problems verwendet   <https://docs.microsoft.com/archive/blogs/dmcat/profiling-entity-framework-using-the-visual-studio-2010-profiler> wurde.The "Profiling Entity Framework using the Visual Studio 2010 Profiler" blog post written by the Data and Modeling Customer Advisory Team shows a real-world example of how they used the profiler to investigate a performance problem.  <https://docs.microsoft.com/archive/blogs/dmcat/profiling-entity-framework-using-the-visual-studio-2010-profiler>. Dieser Beitrag wurde für eine Windows-Anwendung geschrieben.This post was written for a windows application. Wenn Sie ein Profil für eine Webanwendung erstellen müssen, funktionieren die Tools für Windows Performance Recorder (WPR) und Windows Performance Analyzer (WPA) möglicherweise besser als die Arbeit in Visual Studio.If you need to profile a web application the Windows Performance Recorder (WPR) and Windows Performance Analyzer (WPA) tools may work better than working from Visual Studio. WPR und WPA sind Teil des Windows Performance Toolkit, das im Windows Assessment and Deployment Kit () enthalten ist http://www.microsoft.com/download/details.aspx?id=39982 .WPR and WPA are part of the Windows Performance Toolkit which is included with the Windows Assessment and Deployment Kit ( http://www.microsoft.com/download/details.aspx?id=39982).

10,2 Anwendung/Datenbankprofil Erstellung10.2 Application/Database profiling

Tools wie der in Visual Studio integrierte Profiler zeigen Ihnen, wo Ihre Anwendung Zeit verbringt.Tools like the profiler built into Visual Studio tell you where your application is spending time.Ein weiterer Profiler ist verfügbar, der eine dynamische Analyse ihrer ausgeführten Anwendung ausführt, je nach Anforderungen in der Produktions-oder der Präproduktionsumgebung, und nach häufigen Fehlerquellen und Antimustern des Datenbankzugriffs sucht.  Another type of profiler is available that performs dynamic analysis of your running application, either in production or pre-production depending on needs, and looks for common pitfalls and anti-patterns of database access.

Zwei kommerziell verfügbare Profiler sind der Entity Framework Profiler ( <http://efprof.com> ) und ormprofiler ( <http://ormprofiler.com> ).Two commercially available profilers are the Entity Framework Profiler ( <http://efprof.com>) and ORMProfiler ( <http://ormprofiler.com>).

Wenn es sich bei Ihrer Anwendung um eine MVC-Anwendung handelt, die Code First verwendet, können Sie den stackexchange-miniprofiler verwenden.If your application is an MVC application using Code First, you can use StackExchange's MiniProfiler. Scott Hanselman beschreibt dieses Tool in seinem Blog unter: <http://www.hanselman.com/blog/NuGetPackageOfTheWeek9ASPNETMiniProfilerFromStackExchangeRocksYourWorld.aspx> .Scott Hanselman describes this tool in his blog at: <http://www.hanselman.com/blog/NuGetPackageOfTheWeek9ASPNETMiniProfilerFromStackExchangeRocksYourWorld.aspx>.

Weitere Informationen zur Profilerstellung für die Datenbankaktivität Ihrer Anwendung finden Sie im MSDN Magazine-Artikel der Julie Lerman im Entity Framework.For more information on profiling your application's database activity, see Julie Lerman's MSDN Magazine article titled Profiling Database Activity in the Entity Framework.

10,3 Daten Bank Protokollierung10.3 Database logger

Wenn Sie Entity Framework 6 verwenden, sollten Sie auch die Verwendung der integrierten Protokollierungsfunktionen in Erwägung gezogen.If you are using Entity Framework 6 also consider using the built-in logging functionality. Die Daten Bank Eigenschaft des Kontexts kann angewiesen werden, die Aktivität über eine einfache einzeilige Konfiguration zu protokollieren:The Database property of the context can be instructed to log its activity via a simple one-line configuration:

    using (var context = newQueryComparison.DbC.NorthwindEntities())
    {
        context.Database.Log = Console.WriteLine;
        var q = context.Products.Where(p => p.Category.CategoryName == "Beverages");
        q.ToList();
    }

In diesem Beispiel wird die Datenbankaktivität in der Konsole protokolliert, die Log-Eigenschaft kann jedoch so konfiguriert werden, dass jeder beliebige Aktions Zeichen folgen Delegat aufgerufen wird < > .In this example the database activity will be logged to the console, but the Log property can be configured to call any Action<string> delegate.

Wenn Sie die Daten Bank Protokollierung ohne Neukompilierung aktivieren möchten, und Sie Entity Framework 6,1 oder höher verwenden, fügen Sie einen Interceptor in der web.config-oder app.config-Datei Ihrer Anwendung hinzu.If you want to enable database logging without recompiling, and you are using Entity Framework 6.1 or later, you can do so by adding an interceptor in the web.config or app.config file of your application.

  <interceptors>
    <interceptor type="System.Data.Entity.Infrastructure.Interception.DatabaseLogger, EntityFramework">
      <parameters>
        <parameter value="C:\Path\To\My\LogOutput.txt"/>
      </parameters>
    </interceptor>
  </interceptors>

Weitere Informationen zum Hinzufügen der Protokollierung ohne Neukompilieren finden Sie unter <http://blog.oneunicorn.com/2014/02/09/ef-6-1-turning-on-logging-without-recompiling/> .For more information on how to add logging without recompiling go to <http://blog.oneunicorn.com/2014/02/09/ef-6-1-turning-on-logging-without-recompiling/>.

11 Anhang11 Appendix

11,1 A. Test Umgebung11.1 A. Test Environment

In dieser Umgebung wird eine 2-Computer-Einrichtung mit der Datenbank auf einem anderen Computer als die Client Anwendung verwendet.This environment uses a 2-machine setup with the database on a separate machine from the client application. Computer befinden sich im gleichen Rack, sodass die Netzwerk Latenz relativ gering, aber realistischer ist als eine Umgebung mit einem einzigen Computer.Machines are in the same rack, so network latency is relatively low, but more realistic than a single-machine environment.

11.1.1-App-Server11.1.1       App Server

11.1.1.1-Software Umgebung11.1.1.1      Software Environment
  • Entity Framework 4-Software UmgebungEntity Framework 4 Software Environment
    • Betriebssystem Name: Windows Server 2008 R2 Enterprise SP1.OS Name: Windows Server 2008 R2 Enterprise SP1.
    • Visual Studio 2010 – Ultimate.Visual Studio 2010 – Ultimate.
    • Visual Studio 2010 SP1 (nur für einige Vergleiche).Visual Studio 2010 SP1 (only for some comparisons).
  • Entity Framework 5-und 6-Software UmgebungEntity Framework 5 and 6 Software Environment
    • Betriebssystem Name: Windows 8.1 EnterpriseOS Name: Windows 8.1 Enterprise
    • Visual Studio 2013 – Ultimate.Visual Studio 2013 – Ultimate.
11.1.1.2-Hardware Umgebung11.1.1.2      Hardware Environment
  • Dual Prozessor: Intel (r) Xeon (r) CPU L5520 W3530 @ 2,27 GHz, 2261 Mhz8 GHz, 4 Kerne (e), 84 logische Prozessoren.Dual Processor:     Intel(R) Xeon(R) CPU L5520 W3530 @ 2.27GHz, 2261 Mhz8 GHz, 4 Core(s), 84 Logical Processor(s).
  • 2412 GB ramram.2412 GB RamRAM.
  • 136 GB SCSI250GB SATA 7200 rpm, 3 GB/s, in 4 Partitionen aufgeteilt.136 GB SCSI250GB SATA 7200 rpm 3GB/s drive split into 4 partitions.

11.1.2 DB-Server11.1.2       DB server

11.1.2.1-Software Umgebung11.1.2.1      Software Environment
  • Betriebssystem Name: Windows Server 2008 r 28,1 Enterprise SP1.OS Name: Windows Server 2008 R28.1 Enterprise SP1.
  • SQL Server 2008 R22012.SQL Server 2008 R22012.
11.1.2.2-Hardware Umgebung11.1.2.2      Hardware Environment
  • Einzelner Prozessor: Intel (r) Xeon (r) CPU L5520 @ 2,27 GHz, 2261 mhzes-1620 0 @ 3,60 GHz, 4 Kerne (e), 8 logische Prozessoren.Single Processor: Intel(R) Xeon(R) CPU L5520  @ 2.27GHz, 2261 MhzES-1620 0 @ 3.60GHz, 4 Core(s), 8 Logical Processor(s).
  • 824 GB ramram.824 GB RamRAM.
  • 465 GB ATA500GB SATA 7200 rpm, 6-GB/s, in 4 Partitionen aufgeteilt.465 GB ATA500GB SATA 7200 rpm 6GB/s drive split into 4 partitions.

11,2 B. Abfragen von Leistungs Vergleichstests11.2      B. Query performance comparison tests

Das Northwind-Modell wurde verwendet, um diese Tests auszuführen.The Northwind model was used to execute these tests. Es wurde mit dem Entity Framework-Designer aus der Datenbank generiert.It was generated from the database using the Entity Framework designer. Anschließend wurde der folgende Code verwendet, um die Leistung der Abfrage Ausführungs Optionen zu vergleichen:Then, the following code was used to compare the performance of the query execution options:

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Data.Entity.Infrastructure;
using System.Data.EntityClient;
using System.Data.Objects;
using System.Linq;

namespace QueryComparison
{
    public partial class NorthwindEntities : ObjectContext
    {
        private static readonly Func<NorthwindEntities, string, IQueryable<Product>> productsForCategoryCQ = CompiledQuery.Compile(
            (NorthwindEntities context, string categoryName) =>
                context.Products.Where(p => p.Category.CategoryName == categoryName)
                );

        public IQueryable<Product> InvokeProductsForCategoryCQ(string categoryName)
        {
            return productsForCategoryCQ(this, categoryName);
        }
    }

    public class QueryTypePerfComparison
    {
        private static string entityConnectionStr = @"metadata=res://*/Northwind.csdl|res://*/Northwind.ssdl|res://*/Northwind.msl;provider=System.Data.SqlClient;provider connection string='data source=.;initial catalog=Northwind;integrated security=True;multipleactiveresultsets=True;App=EntityFramework'";

        public void LINQIncludingContextCreation()
        {
            using (NorthwindEntities context = new NorthwindEntities())
            {                 
                var q = context.Products.Where(p => p.Category.CategoryName == "Beverages");
                q.ToList();
            }
        }

        public void LINQNoTracking()
        {
            using (NorthwindEntities context = new NorthwindEntities())
            {
                context.Products.MergeOption = MergeOption.NoTracking;

                var q = context.Products.Where(p => p.Category.CategoryName == "Beverages");
                q.ToList();
            }
        }

        public void CompiledQuery()
        {
            using (NorthwindEntities context = new NorthwindEntities())
            {
                var q = context.InvokeProductsForCategoryCQ("Beverages");
                q.ToList();
            }
        }

        public void ObjectQuery()
        {
            using (NorthwindEntities context = new NorthwindEntities())
            {
                ObjectQuery<Product> products = context.Products.Where("it.Category.CategoryName = 'Beverages'");
                products.ToList();
            }
        }

        public void EntityCommand()
        {
            using (EntityConnection eConn = new EntityConnection(entityConnectionStr))
            {
                eConn.Open();
                EntityCommand cmd = eConn.CreateCommand();
                cmd.CommandText = "Select p From NorthwindEntities.Products As p Where p.Category.CategoryName = 'Beverages'";

                using (EntityDataReader reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess))
                {
                    List<Product> productsList = new List<Product>();
                    while (reader.Read())
                    {
                        DbDataRecord record = (DbDataRecord)reader.GetValue(0);

                        // 'materialize' the product by accessing each field and value. Because we are materializing products, we won't have any nested data readers or records.
                        int fieldCount = record.FieldCount;

                        // Treat all products as Product, even if they are the subtype DiscontinuedProduct.
                        Product product = new Product();  

                        product.ProductID = record.GetInt32(0);
                        product.ProductName = record.GetString(1);
                        product.SupplierID = record.GetInt32(2);
                        product.CategoryID = record.GetInt32(3);
                        product.QuantityPerUnit = record.GetString(4);
                        product.UnitPrice = record.GetDecimal(5);
                        product.UnitsInStock = record.GetInt16(6);
                        product.UnitsOnOrder = record.GetInt16(7);
                        product.ReorderLevel = record.GetInt16(8);
                        product.Discontinued = record.GetBoolean(9);

                        productsList.Add(product);
                    }
                }
            }
        }

        public void ExecuteStoreQuery()
        {
            using (NorthwindEntities context = new NorthwindEntities())
            {
                ObjectResult<Product> beverages = context.ExecuteStoreQuery<Product>(
@"    SELECT        P.ProductID, P.ProductName, P.SupplierID, P.CategoryID, P.QuantityPerUnit, P.UnitPrice, P.UnitsInStock, P.UnitsOnOrder, P.ReorderLevel, P.Discontinued
    FROM            Products AS P INNER JOIN Categories AS C ON P.CategoryID = C.CategoryID
    WHERE        (C.CategoryName = 'Beverages')"
);
                beverages.ToList();
            }
        }

        public void ExecuteStoreQueryDbContext()
        {
            using (var context = new QueryComparison.DbC.NorthwindEntities())
            {
                var beverages = context.Database.SqlQuery\<QueryComparison.DbC.Product>(
@"    SELECT        P.ProductID, P.ProductName, P.SupplierID, P.CategoryID, P.QuantityPerUnit, P.UnitPrice, P.UnitsInStock, P.UnitsOnOrder, P.ReorderLevel, P.Discontinued
    FROM            Products AS P INNER JOIN Categories AS C ON P.CategoryID = C.CategoryID
    WHERE        (C.CategoryName = 'Beverages')"
);
                beverages.ToList();
            }
        }

        public void ExecuteStoreQueryDbSet()
        {
            using (var context = new QueryComparison.DbC.NorthwindEntities())
            {
                var beverages = context.Products.SqlQuery(
@"    SELECT        P.ProductID, P.ProductName, P.SupplierID, P.CategoryID, P.QuantityPerUnit, P.UnitPrice, P.UnitsInStock, P.UnitsOnOrder, P.ReorderLevel, P.Discontinued
    FROM            Products AS P INNER JOIN Categories AS C ON P.CategoryID = C.CategoryID
    WHERE        (C.CategoryName = 'Beverages')"
);
                beverages.ToList();
            }
        }

        public void LINQIncludingContextCreationDbContext()
        {
            using (var context = new QueryComparison.DbC.NorthwindEntities())
            {                 
                var q = context.Products.Where(p => p.Category.CategoryName == "Beverages");
                q.ToList();
            }
        }

        public void LINQNoTrackingDbContext()
        {
            using (var context = new QueryComparison.DbC.NorthwindEntities())
            {
                var q = context.Products.AsNoTracking().Where(p => p.Category.CategoryName == "Beverages");
                q.ToList();
            }
        }
    }
}

11,3 C. Navision-Modell11.3 C. Navision Model

Die Navision-Datenbank ist eine große Datenbank, die für die Demo von Microsoft Dynamics – NAV verwendet wird.The Navision database is a large database used to demo Microsoft Dynamics – NAV. Das generierte konzeptionelle Modell enthält 1005 Entitätenmengen und 4227 Zuordnungs Sätze.The generated conceptual model contains 1005 entity sets and 4227 association sets. Das im Test verwendete Modell ist "Flat" – Es wurde keine Vererbung hinzugefügt.The model used in the test is “flat” – no inheritance has been added to it.

11.3.1-Abfragen, die für Navision-Tests verwendet werden11.3.1 Queries used for Navision tests

Die mit dem Navision-Modell verwendete Abfrage Liste enthält drei Kategorien Entity SQL Abfragen:The queries list used with the Navision model contains 3 categories of Entity SQL queries:

11.3.1.1-Suche11.3.1.1 Lookup

Eine einfache Suchabfrage ohne AggregationenA simple lookup query with no aggregations

  • Anzahl: 16232Count: 16232
  • Beispiel:Example:
  <Query complexity="Lookup">
    <CommandText>Select value distinct top(4) e.Idle_Time From NavisionFKContext.Session as e</CommandText>
  </Query>
11.3.1.2 singleaggregating11.3.1.2 SingleAggregating

Eine normale BI-Abfrage mit mehreren Aggregationen, aber keine Teilergebnisse (einzelne Abfrage)A normal BI query with multiple aggregations, but no subtotals (single query)

  • Anzahl: 2313Count: 2313
  • Beispiel:Example:
  <Query complexity="SingleAggregating">
    <CommandText>NavisionFK.MDF_SessionLogin_Time_Max()</CommandText>
  </Query>

Wenn MDF _ sessionlogin _ time _ Max () im Modell wie folgt definiert ist:Where MDF_SessionLogin_Time_Max() is defined in the model as:

  <Function Name="MDF_SessionLogin_Time_Max" ReturnType="Collection(DateTime)">
    <DefiningExpression>SELECT VALUE Edm.Min(E.Login_Time) FROM NavisionFKContext.Session as E</DefiningExpression>
  </Function>
11.3.1.3 aggregatingsubsummen11.3.1.3 AggregatingSubtotals

Eine BI-Abfrage mit Aggregationen und Teilsummen (über Union all)A BI query with aggregations and subtotals (via union all)

  • Anzahl: 178Count: 178
  • Beispiel:Example:
  <Query complexity="AggregatingSubtotals">
    <CommandText>
using NavisionFK;
function AmountConsumed(entities Collection([CRONUS_International_Ltd__Zone])) as
(
    Edm.Sum(select value N.Block_Movement FROM entities as E, E.CRONUS_International_Ltd__Bin as N)
)
function AmountConsumed(P1 Edm.Int32) as
(
    AmountConsumed(select value e from NavisionFKContext.CRONUS_International_Ltd__Zone as e where e.Zone_Ranking = P1)
)
----------------------------------------------------------------------------------------------------------------------
(
    select top(10) Zone_Ranking, Cross_Dock_Bin_Zone, AmountConsumed(GroupPartition(E))
    from NavisionFKContext.CRONUS_International_Ltd__Zone as E
    where AmountConsumed(E.Zone_Ranking) > @MinAmountConsumed
    group by E.Zone_Ranking, E.Cross_Dock_Bin_Zone
)
union all
(
    select top(10) Zone_Ranking, Cast(null as Edm.Byte) as P2, AmountConsumed(GroupPartition(E))
    from NavisionFKContext.CRONUS_International_Ltd__Zone as E
    where AmountConsumed(E.Zone_Ranking) > @MinAmountConsumed
    group by E.Zone_Ranking
)
union all
{
    Row(Cast(null as Edm.Int32) as P1, Cast(null as Edm.Byte) as P2, AmountConsumed(select value E
                                                                         from NavisionFKContext.CRONUS_International_Ltd__Zone as E
                                                                         where AmountConsumed(E.Zone_Ranking) > @MinAmountConsumed))
}</CommandText>
    <Parameters>
      <Parameter Name="MinAmountConsumed" DbType="Int32" Value="10000" />
    </Parameters>
  </Query>