Working with Objects
The Entity Framework enables you to query, insert, update, and delete data, which is expressed as typed common language runtime (CLR) objects that are instances of entity types. The entity types represent the entities defined in the conceptual model. The Entity Framework maps entities and relationships that are defined in a conceptual model to a data source. The Entity Framework provides facilities to do the following: materialize data returned from the data source as objects; track changes that were made to the objects; handle concurrency; propagate object changes back to the data source; and bind objects to controls. You can use LINQ to Entities, Entity SQL Language, or Query Builder Methods to execute queries against the conceptual model. For more information, see Querying a Conceptual Model.
The Entity Framework provides tools that automatically generate an object layer based on the conceptual model. The object layer includes entity types and object context definitions. The object context definition contains an ObjectContext derived class that typically has a set of properties that return a collection of entities of the specified type. To generate the object layer code, use the Entity Data Model Designer (Entity Designer) or the EdmGen.exe command-line tool. For more information, see Generated Code Overview.
This topic discusses the object context class and the types of entities supported by the Entity Framework.
The ObjectContext class is the primary class for interacting with entity objects. An instance of the ObjectContext class encapsulates the following: a connection to the database; metadata that describes the model; and an ObjectStateManager object that tracks objects during create, update, and delete operations.
The lifetime of the ObjectContext begins when the instance is created and ends when the instance is either disposed or garbage-collected. Use using if you want all the resources that the context controls to be disposed at the end of the block. When you use using, the compiler creates a try/finally block and calls dispose in the finally block. Here are some general guidelines when deciding on the lifetime of the object context:
When working with long-running object context consider the following:
As you load more objects and their references into memory, the object context may grow quickly in memory consumption. This may cause performance issues.
Remember to dispose of the context when it is no longer required.
If an exception caused the object context to be in an unrecoverable state, the whole application may terminate.
The chances of running into concurrency-related issues increase as the gap between the time when the data is queried and updated grows.
- As you load more objects and their references into memory, the object context may grow quickly in memory consumption. This may cause performance issues.
When working with Web applications, use an object context instance per request. If you want to track changes in your objects between the tiers, use the self-tracking entities. For more information, see Working with Self-Tracking Entities and Building N-Tier Applications.
When working with Windows Presentation Foundation (WPF) or Windows Forms, use an object context instance per form. This lets you use change tracking functionality that object context provides.
By default, the object context manages connections to the database. The object context opens and closes connections as needed. For example, the object context opens connection to execute a query, and then closes the connection when all the result sets have been processed.
There are cases when you want to have more control over when the connection opens and closes. For example, when working with SQL Server Compact, opening and closing the same connection is expensive. You can manage this process manually by using the Connection property. For more information, see Managing Connections and Transactions.
The ObjectContext is not thread safe. You can still create a multithreaded application as long as an instance of this class is not shared between threads. If you plan to transfer entity objects from one thread to another, make sure you call Detach on each entity before sending it to another thread. For more information, see Attaching and Detaching Objects.
The following topics provide more information about how to manage the object context, including managing connections and transactions, attaching objects, working with relationships, and managing change tracking and identity resolution:
In the Entity Framework, you can work with entity types that derive from EntityObject, "plain-old" CLR objects (POCO) types, POCO proxy types, and self-tracking entity types. The following sections give information that may help you decide what option is appropriate, given the nature of your application.
By default, the ADO.NET Entity Data Model tools generate EntityObject derived entity types. When you work with EntityObject derived types, the object context manages the relationships between your objects, tracks changes as they occur, and supports lazy loading in the most efficient manner. However, the EntityObject derived types have strong dependency on the Entity Framework. If you are working with architectures that require persistence ignorance (for example, test- driven development or domain-driven development) or you have existing domain classes, consider using POCO or POCO proxies.
The Entity Framework enables you to use existing domain objects together with the data model without making any modifications to the data classes. These POCO data classes (also known as persistence-ignorant objects) support most of the same query, insert, update, and delete behaviors as entity types that are generated by the Entity Data Model tools.
When you work with POCO types, changes that are made to the object graph are not tracked automatically by the Entity Framework as they occur. The Entity Framework uses the snapshot mechanism to detect the changes to the objects. Call DetectChanges to synchronize object context with your graph. By default, the object context calls this method before saving the data to the data source. This mechanism uses more memory than the instant notification mechanism and could affect your performance, especially if the application requires detecting changes frequently. For more information, see Tracking Changes in POCO Entities. To have an instant notification support, enable the creation of change-tracking proxy objects.
If you want to take advantage of lazy loading, you need to enable lazy loading proxy creation. For more information, see POCO Proxy section below.
Use POCO proxies if you want very efficient and instant change tracking and lazy loading. When you use proxies, you have the same functionality as EntityObject derived types but still separate your domain classes from the Entity Framework. To enable lazy loading proxy and/or instant change tracking proxy creation, your POCO classes must meet the requirements described in the Requirements for Creating POCO Proxies topic.
Proxies are created during runtime and inherit from POCO types. This means that the runtime type of your entities differs from the POCO type. This introduces some complications with serialization. For more information, see Working with POCO Entities. Note that creating proxy types has some overhead compare to POCO types.
The EntityObject derived types, POCO, and POCO proxy types work well in applications where entity objects can be attached to the object context that handles change tracking. However, when you have to transfer full graphs of entities to a tier where the object context is not available, you must decide how to track changes and report those changes back to the object context. Starting with the .NET Framework version 4, self-tracking entities can record changes to scalar, complex, and navigation properties. Self-tracking entities do not depend on the Entity Framework. The ADO.NET Self-Tracking Entity Generator template generates self-tracking entities. For more information, see Working with Self-Tracking Entities.
The following performance considerations may also help choosing what types of objects are best suited for your application.
When loading metadata, the cost of discovering POCO or proxy types is greater than discovering attributed EntityObject derived types.
There is some overhead involved in generating dynamic POCO proxy types.
Initializing POCO types involves the least overhead compare to proxy and EntityObject derived types.
POCO snapshot tracking is more costly than instant notification tracking.