Building N-Tier Applications
The Entity Framework supports serializing entity objects into formats that enable remote and message-based exchange of entity objects, such as those used with Web services and the Windows Communication Foundation (WCF). Objects can be serialized by using binary serialization, XML serialization, and WCF contract serialization for transport by using binary stream or message-based protocols. For more information, see Serializing Objects. Objects can also be received from a message or stream, deserialized, and attached to an object context. For more information, see Attaching and Detaching Objects.
WCF Data Services enables you to provide dynamic access to entity data in an XML format that can be used by applications. Access this entity data by using standard representational state transfer (REST) HTTP actions, such as GET, PUT, and POST. For more information, see WCF Data Services.
The following considerations apply to Web services or WCF services that use the Entity Framework:
With binary serialization and data contract serialization, related objects are serialized together with the primary object. XML serialization does not serialize related objects. When serializing entities, disable lazy loading. Lazy loading performs a query for each relationship navigation property that is accessed, and both binary and WCF data contract serializers access all relationship navigation properties. This can cause many unexpected queries to be performed during serialization. For more information, see Serializing Objects.
Stateless services are recommended. Services should be designed such that an object context is only maintained for the duration of a request or a response. The message exchange pattern should include enough information so that changes can be applied without having to persist objects or re-query the data source to retrieve the original object. For example, a service that allows a client to update objects should require that the updated object be returned along with the original object. This enables changes to be applied to the original object by the Web service without having to retrieve the original object from the database or persist it in memory. For more information, see How to: Apply Changes Made to a Detached Object.
Objects are always deserialized in the Detached state. You may need to attach or add the object to an ObjectContext, or you may just want to apply property changes to the original object. For more information, see Attaching and Detaching Objects.
Once the objects and the relationships are added to the context, you can set the new state by using ChangeObjectState (such as Added or Modified).
You must manually manage concurrency and validation.
For more information, see the following articles on N-Tier development:
Anti-Patterns To Avoid In N-Tier Applications
Self-Tracking Entities
In an Entity Framework application, an object context is responsible for tracking changes in your objects. However, when you need to manipulate objects in another tier, where the object context is not available, you must decide how to track changes report those changes back to the object context. Starting with the .NET Framework version 4, self-tracking entities can help you track changes in any tier. A self-tracking entity is an entity built from a Text Template Transformation Toolkit (T4) template that generates entity types that have the ability to record changes to scalar, complex, and navigation properties. For more information, see Working with Self-Tracking Entities.
To track changes on a tier where objects are not attached to an object context without using self-tracking entities, you can use the methods in the following section to help you update your context to persist the relevant changes to the database.
Working with APIs Relevant to N-Tier Application Development
The following methods enable you to add an entire graph of objects and then walk over that graph, apply the appropriate values to the properties of the object, and set the correct state on entity objects and relationships.
To add and attach entities, use the following methods:
Member | Description |
---|---|
System.Data.Objects.ObjectSet.AddObject( or System.Data.Objects.ObjectContext.AddObject(System.String,System.Object) |
Adds an object and its related objects to the ObjectContext and sets the entity objects to the Added state. In this state, the entity objects are not required to have unique key values. The temporary key values are assigned to key properties and are updated with the data source-generated values after you save the objects. After you have added the objects, change the state of the entity objects appropriately. |
System.Data.Objects.ObjectSet.Attach( or System.Data.Objects.ObjectContext.Attach(System.Data.Objects.DataClasses.IEntityWithKey) and |
Adds an object to the ObjectContext and sets the object to the Unchanged state. In the Unchanged state, the Entity Framework treats the entity key values as final. If more than one entity of a particular type has the same key value, the Entity Framework will throw an exception. To avoid getting the exception, use the AddObject method to attach the detached objects and then change the state appropriately. |
To change scalar values, use the following methods:
Member | Description |
---|---|
System.Data.Objects.ObjectSet.ApplyCurrentValues( or System.Data.Objects.ObjectContext.ApplyCurrentValues.String, |
Copies the scalar values from the supplied object into the object in the ObjectContext that has the same key. Any values that differ from the original values will be marked as modified. If you have a graph with current values and want to apply the original values, call ApplyOriginalValues method. You may also use the ApplyCurrentValues method of the ObjectStateEntry. |
System.Data.Objects.ObjectSet.ApplyOriginalValues( or System.Data.Objects.ObjectContext.ApplyOriginalValues.String, |
Copies the scalar values from the supplied object into set of original values for the object in the ObjectContext that has the same key. Any values that differ from the current values will be marked as modified. You may also use the ApplyOriginalValues method of the ObjectStateEntry. |
Sets individual properties to the Modified state. Use this property when you know what properties were modified instead of setting the whole entity to modified. |
|
Gets the OriginalValueRecord instance that represents the updatable version of the original values of the object that is associated with this ObjectStateEntry. Use the returned OriginalValueRecord instance to read or update the original properties of the object individually. |
|
Gets the CurrentValueRecord instance that represents the current values of the object that is associated with this ObjectStateEntry. Use the returned CurrentValueRecord instance to read or update the current properties of the object individually. |
To change entity and relationship state, use the following methods:
Member | Description |
---|---|
ChangeObjectState |
Changes an entity or relationship to a new state (such as Added or Modified). This change may have an impact on the relationships that an entity participates in. For example, moving an entity to the Added state will also move any unchanged relationships to the Added state. Similarly, marking an entity as Modified will mark all scalar values as Modified. You may also use the ChangeState method of the ObjectStateEntry. |
Changes the existing relationship between two entities to the specified state. If there is no relationship between the entities, this method will create a new one in the specified state. This method is not supported for relationships based on a foreign key association. For more information, Defining and Managing Relationships. You may also use the ChangeState method of the ObjectStateEntry. |
|
ChangeState |
This method behaves the same as ChangeObjectState or ChangeRelationshipState depending on whether the ObjectStateEntry is an object or a relationship. |
SetModifiedProperty |
Sets individual properties to the Modified state. Use this method when you know what properties were modified instead of setting the whole entity to modified. |
To save changes to the data source, use the following methods:
Member | Description |
---|---|
Persists all changes to the data source. |
Use the ObjectMaterialized event if you want to get or set some information, or subscribe to some events, during the materialization of the object.
Member | Description |
---|---|
ObjectMaterialized |
Occurs when a new entity object is created from data in the data source as part of a query or load operation. The event is raised after reference objects are loaded, but before collections are loaded. If an object that has the same key value exists in the context, the Entity Framework will not recreate the object and this event will not be raised. |