Use OrganizationServiceContext

In Common Data Service, you can use the several classes that implement the IOrganizationService interface to access the Web services. Alternatively, you can use the OrganizationServiceContext generated by the code generation tool to gain access to additional functionality. The OrganizationServiceContext class lets you track changes, manage identities and relationships, and gives you access to the LINQ provider. This class also contains a OrganizationServiceContext.SaveChanges() method that you use to submit the changes to data that the context is tracking. This class is based on the same concept as the DataServiceContext class in Windows Communication Foundation (WCF) Data Services.

To generate this class, provide a value for the /serviceContextName parameter when you generate early bound types. The code generation tool uses this name as the name of the generated class. For more information about how to use the code generation tool, see Generate classes for early-bound programming using the Organization service. You can use the organization service context when you develop applications, plug-ins, and workflow activities.

How to use the OrganizationServiceContext class

To instantiate the context class, you must pass the class constructor an object that implements the IOrganizationService interface. One option is to pass an instance of the CrmServiceClient class. For more information about the IOrganizationService interface, see IOrganizationService Interface.

The following code example shows how to create a new instance of the context class. In this example, the context class was named AdventureWorksCycleServiceContext by specifying the name using the /serviceContextName parameter on the code generation tool:

//For early bound types to work correctly, they have to be enabled on the proxy.  
_serviceProxy.EnableProxyTypes();  
AdventureWorksCycleServiceContext context = new AdventureWorksCycleServiceContext(svc);  

After you create the organization service context object, you can begin to track create, modify, or delete entities.

The organization service context must track any entity or relationship that you want to submit to Common Data Service. For example, you could retrieve a record with a LINQ query and the context would track that entity or you could use the OrganizationServiceContext.Attach(Entity) method to cause the context to begin tracking the entity. You can work with data in a client application and create new entities, create related entities, and modify existing entities, but you must call the SaveChanges method on tracked entities to commit changes to Common Data Service.

Track changes

To determine how an entity is tracked by the context, you can check the EntityState property on the entity instance. You must notify the organization service context to track an entity from Common Data Service by calling various methods or by using a LINQ query. All entities returned from a LINQ query are tracked by the service context.

You can add objects to the service context by calling one of the following methods in OrganizationServiceContext.

Method Use
AddObject(Entity) Adds an entity to the set of entities the organization service context is tracking. The status of the entity in the context is set to Created. If the SaveChanges() method is called, this record will be created or added to the server.
Attach(Entity) Adds an entity to the set of entities the organization service context is tracking. The status of the entity in the context is set to Unchanged. If the SaveChanges() method is called, this entity will not be sent to the server unless its status changes.
CreateQuery(String) Adds the results of a query to the set of entities the organization service context is tracking.

In Common Data Service, the organization service context lets you create and update relationships between entities. The navigation properties generated by the CrmSvcUtil.exe tool and located in the early-bound classes let you access and change related entity properties and relationships. The organization service context must be tracking the related entity for the related entity to be available to be updated on the server.

Use the following methods in OrganizationServiceContext to work with related entities and to add the entity to the service context:

Method Use
AddRelatedObject(Entity, Relationship, Entity) Adds the target to the context. Calls the Attach(Entity) method on the target entity and then calls the AddLink(Entity, Relationship, Entity) method between the source entity and the target (related) entity.
AttachLink(Entity, Relationship, Entity) Adds the related entity to the context for tracking. The status of the entity in the context is set to Unchanged.
AddLink(Entity, Relationship, Entity) Creates a relationship between the source and target entities. Adds the target to the context. The status of the target entity in the context is set to Created.
LoadProperty(Entity, String) Loads the related entity set for the specified relationship. Gives access to related entities by using the navigation property. Call the AddObject(Entity) method on the related entity after you have accessed the entity by using a navigation property on the parent entity.
UpdateObject(Entity) Changes the state of the specified entity in the OrganizationServiceContext to Modified.
DeleteObject(Entity) Changes the state of the specified entity to be deleted in the OrganizationServiceContext.

Related entities for entities you have retrieved using LINQ will be null until you use LoadProperty(Entity, Relationship) to retrieve them. The following code sample shows how to access Task records associated with a specific Contact record.

Contact pam = context.ContactSet.Where(c => c.FirstName == "Pamela").FirstOrDefault();  
if (pam != null)  
{  
// pam.Contact_Tasks is null until you use LoadProperty  
    context.LoadProperty(pam, "Contact_Tasks");  
    Task firstTask = pam.Contact_Tasks.FirstOrDefault();  
}  

You can use the AddLink(Entity, Relationship, Entity) method to create associations. You must call the SaveChanges() method before the server is updated with the new link information.

The following code example shows how to create an association between a contact and an account.

Relationship relationship = new Relationship("account_primary_contact");  
context.AddLink(contact, relationship, account);  
context.SaveChanges();  

Save changes

The organization service context holds a graph of the entities it is tracking. The order in which the organization service context processes entity changes and submits them to the server is important. Updates to primary entity are processed, and then related entities are processed. If a value is set on the primary entity by the related entity, that value is used when updating data on the server.

If an error occurs when entity information is being saved, a new exception type that contains the SaveChangesResult is thrown by the OrganizationServiceContext.SaveChanges() method, regardless of the value of the SaveChangesOptions parameter that is passed into the method.

Use virtual methods when the context is changed

Sometimes it may be necessary to take actions based on changes in the OrganizationServiceContext. To facilitate this, virtual methods are provided to allow you to intercept or be notified of an operation. To take advantage of these methods, you either have to derive from OrganizationServiceContext or change the generated organization service context.The following table lists the virtual methods.

Method Description
OnBeginEntityTracking(Entity) Called after an entity is attached to the OrganizationServiceContext.
OnBeginLinkTracking(Entity, Relationship, Entity) Called after a link is attached to the OrganizationServiceContext.
OnEndEntityTracking(Entity) Called after an entity is detached from the OrganizationServiceContext.
OnEndEntityTracking(Entity) Called after a link is detached from the OrganizationServiceContext.
OnExecuting(OrganizationRequest) Called immediately before a request is submitted to Common Data Service.
OnExecute(OrganizationRequest, OrganizationResponse) Called immediately after a request is submitted to the Common Data Service, regardless of whether an exception occurred or not.
OnSavingChanges(SaveChangesOptions) Called before any operations occur after a call to SaveChanges.
OnSaveChanges(SaveChangesResultCollection) Called when all of the operations for a call to SaveChanges have completed, or when there is a failure.

Data Operations

You can modify, create, and delete objects in the organization service context, and Common Data Service tracks the changes that you made to these objects. When the OrganizationServiceContext.SaveChanges() method is called, Common Data Service generates and executes commands that perform the equivalent insert, update, or delete statements against data in Common Data Service.

When working with early-bound entity classes, you use the entity name and attribute schema name to specify an entity or attribute to work with. Attribute schema names are defined in EntityMetadata.SchemaName and AttributeMetadata.SchemaName, or you can use the class and property names shown in the code-generated file.The following sample shows how to assign a value to the email attribute of a new contact instance.

Contact contact = new Contact();
contact.EMailAddress1 = “sonny@contoso.com”;  

Create a new entity record

When you want to insert data into Common Data Service by using the entity data model, you must create an instance of an entity type and add the object to an organization service context. The organization service context must be tracking the object before it can save the object to Common Data Service.

When creating a new entity record, you add the object to the organization service context by using the AddObject(Entity). method.

The following sample shows how to instantiate and save a new contact record by using the entity data model. It also demonstrates how tp access a custom attribute.

OrganizationServiceContext orgContext =new OrganizationServiceContext(svc);  
Contact contact = new Contact()     
 {  
   FirstName = "Charles",  
   LastName = "Brown",  
   Address1_Line1 = "123 Main St.",  
   Address1_City = "Des Moines",  
   Address1_StateOrProvince = "IA",  
   Address1_PostalCode = "21254",  
   new_twittername = "Chuck",  
   Telephone1 = "123-234-5678"  
 };   
orgContext.AddObject(contact);
orgContext.SaveChanges();  

There are several points to note in the previous code example. First, after a new contact is instantiated, you pass that contact object to the OrganizationServiceContext.AddObject(Entity) method so the context can begin tracking the object. The second point to note is that the new object is saved to the server by using the OrganizationServiceContext.SaveChanges() method.

After you add an object to the context and before the OrganizationServiceContext.SaveChanges() method is called, the context generates an ID for the new object. An exception that contains the SaveChangesResults is thrown from the SaveChanges() method if any updates to the Common Data Service data fail.

Update an entity record

Common Data Service tracks changes to objects that are attached to the organization service context. To modify an existing entity record, you must first add the object to the context. To add an object to the context, you must first retrieve the entity record from Common Data Service and then add the object to the context by using the Attach(Entity) method. Once the object is being tracked by the context, you can update the record by setting the entity’s attributes.

The following sample shows how to update an account attribute by using early bound classes.

Account.EMailAddress1 = “Contoso-WebMaster@contoso.com”;  

The following sample shows how to delete an attribute value.

Account.EMailAddress1 = null;  

There are two partial methods named OnPropertyChanging and OnPropertyChanged for each entity. These methods are called in the property setter. You can extend these methods by using partial classes to insert custom business logic.

Delete an entity record

To delete an entity record, the organization service context must be tracking the object. Once the object is on the context, you can use the DeleteObject(Entity) method to mark the object on the context for deletion. Note that the entity record in Common Data Service is not deleted until the OrganizationServiceContext.SaveChanges() method is called.

See also

LINQ query examples using OrganizationServiceContext with Common Data Service
Generate classes for early-bound programming using the Organization service
IOrganizationService
OrganizationServiceContext