Personalized Community is here!
Quickly customize your community to find the content you seek.
Have questions on moving to the cloud? Visit the Dynamics 365 Migration Community today! Microsoft’s extensive network of Dynamics AX and Dynamics CRM experts can help.
2021 Release Wave 2Discover the latest updates and new features releasing from October 2021 through March 2022.
2021 release wave 2 plan
The FastTrack program is designed to help you accelerate your Dynamics 365 deployment with confidence.
FastTrack Community | FastTrack Program | Finance and Operations TechTalks | Customer Engagement TechTalks | Upcoming TechTalks | All TechTalks
If you use LINQ queries with the OrganizationServiceContext then understanding MergeOptions is vital. At the end of this post I describe the most common 'gotcha' that comes from not fully understanding this setting.
The OrganizationServiceContext implements a version of the 'Unit of Work' pattern (http://martinfowler.com/eaaCatalog/unitOfWork.html ) that allows us to make multiple changes on the client and then submit with a single call to 'SaveChanges'. The MergeOption property alters the way that the OrganizationServiceContext handles the automatic tracking of objects when returned from queries. It is important to understand what's going on since by default LINQ queries may not return you the most recent version of the records from the server, but rather a 'stale' versions that is currently being tracked.
The SDK entry on MergeOptions talks about 'Client side changes being lost' during merges.
The term 'merge' is nothing to do with merging of contacts/leads/accounts – but describes what happens when the server is re-queried within an existing context and results from a previous query are returned rather than new copies of each record. It is a record ID based combination, not an attribute merge – so a record is either re-used from the current context, or a new instance is returned that represents the version on the server.
In order to describe the different options, consider the following code:
// Query 1
var contacts = (from c in context.ContactSet
select new Contact
ContactId = c.ContactId,
FirstName = c.FirstName,
LastName = c.LastName,
Address1_City = c.Address1_City
// Update 1
Contact contact1 = contacts;
contact1.Address1_City = DateTime.Now.ToLongTimeString();
// Query 2
var contacts2 = (from c in context.ContactSet
// Update 2
var contact2 = contacts2;
contact2.Address1_City = DateTime.Now.ToLongTimeString();
// Save Changes
Perhaps the best place to start is the behaviour with no tracking at all.
When using the OrganizationServiceContext, by default it will track all objects that are returned from LINQ queries. This means that the second query will return the instance of the contacts that have already been returned from query 1. Critically this means that any changes made on the server between query 1 and query 2 (or any additional attributes queried using projection) will not be returned.
PreserveChanges is essentially the same as AppendOnly except:
The result of this is that queries will not pick up the most recent changes on the server if a tracked version of that record has been edited in the current context.
With a MergeOption of OverwriteChanges, the query behaviour will effectively be as per NoTracking however the tracking behaviour is like AppendOnly and PreserverChanges:
The MergeOption has a subtle but important effect on the OrganizationServiceContext, and without truly understanding each setting you might see unexpected results if you stick with the default 'AppendOnly'. For instance, you might update the value on the server between queries, but because a record is already tracked, re-querying will not bring down the latest values. Remember that all of this behaviour only is true for the same context – so if you are creating a new context then any previously tracked/modified records will no longer be tracked.
The most common issue I see from not fully understanding MergeOptions (and yes I made this mistake too! ) is the use of the default AppendOnly setting in conjunction with LINQ projection. In our code example Query 1 returns a projected version of the contact that only contains 4 attributes. When we re-query in Query 2 we might expect to see all attribute values but because we are already tracking the contacts our query will only return the previously queried 4 attributes! This can hide data from your code and cause some very unexpected results!
In these circumstances, unless you really need tracking and fully understand MergeOptions, I recommend changing the MergeOptions to 'NoTracking'.
Business Applications communities