Performance Best Practice
A well performed CRM system earns millions of happy customers.
Performance is a factor which comes first in every software implementation and Microsoft Dynamics CRM is not an exception. For a successful CRM implementation we must follow some proven practices. The below best practices ensures better performance in CRM implementation. Let’s explore the performance booster ideas.
1. Allow the CRM system to create GUIDs
Dynamics CRM platform uses an internal algorithm to create sequential GUIDs that are used as primary key of a record for CRUD operation. This ensures better indexing which results faster data retrieval from CRM database using CRM SDK.
Below is a sample of Account record creation to ensure the system generates a sequential GUID for the primary key for the record.
Account account =new Account {Name = "The Maestro"}; Guid accountid = crsServiceProxy.Create(account);
But sometimes we need to create our own GUID for some requirements. So for this scenario instead of using Guid.NewGuid() we should use a windows method to generated a sequential GUID on-demand which ensures a sequential GUID.
2. Use Early-Bound Type
We should use Early-bound types when we write codes to extend dynamics CRM. Use of Entity class late-bound concept does not make sure that whether we are specifying the entity name and attribute names correctly at the time of code compilation, this can only be identified at run time which results issues like, The given key was not present in the dictionary, if we are not testing the code thoroughly for all possible scenarios.
Early-Bound Sample Account.Name = "The Maestro";
Late Bound Sample Entity account = new Entity("account"); account["name"] = "The Maestro";
Using early-bound we can exactly select the attribute and entity at compile time so which ensures the attributes and entity names are specified correctly. Although using late-bound i.e. using Entity class results in slightly better performance than early-bound but the recommendation is to use early bound to ensure correct attribute and entity are used in compile time.
Early-bound type class can be generated by using CrmSvcUtil.exe tool which is provided by Microsoft in CRM SDK. Check how to use this tool to create early-bound type. This tool generates early-bound .NET Framework classes that represent the entity data model which is used by Microsoft Dynamics CRM. Check how to write codes using early-bound during development.
3. Write Plug-ins that execute faster
Writing plugins for CRM is very easy and at the same time it’s tricky as well. But think twice before writing a plugin because the plugin code might impact the performance. Every plugin is allowed only 2 minutes to complete its operation. If we write plugins with heavy logic which runs more than 2 minutes then it will throw TimeOut exception.
So keep a note to write plugin code which ensures to execute faster at least within 10-15 seconds. As plugins are synchronous processes, the system performance is impacted in a big way if not handled properly.
There are asynchronous plugins also which can be configured for long executing jobs. But still there is debate when to write asynchronous plugin v/s workflows.
4. Only retrieve required Data Items using SDK
When we retrieve data from CRM database in Plug-ins, Custom Workflow Activities (CWA), Custom asp.net websites, web services & custom batch components using SDK then only select those fields which are actually required to do the task. Don’t retrieve all columns in ColumnSet.
Don’t Use like below new ColumnSet(true);
Use like below way new ColumnSet(“firstname”, “lastname”, “contactid”) };
Take time to mention the columns without being lazy. Using required column names increases the performance in a significant way avoiding unnecessary SQL Generic issues. Before writing a retrieve, determine which columns from an entity are needed first.
5. Limit Operations that Cascades
The OwnerId field is the key which is responsible for cascade operation in CRM. So while updating any record using Update or UpdateRequest method, then do not set OwnerId field for the record unless the owner has actually changed because when we set the attribute, the changes cascade to related entities which increases the time required for the update operation.
6. Use Multi-Threading
Multi-threading increases the processing time in a significant way. Use multi-threads while writing SDK codes using C# to break up the work across multiple CPUs. This works when we use multi-processor system.
7. Disable Plug-ins
Disabled plug-ins before running your application. It’s not a widely used best practice because we normally not disable plugins as the functionality written in the plugin is required. But the suggestion here is to disable the plugin which are not required or less impacted ones before running your application (if possible).
Do not use plugin in Retrieve or RetrieveMultiple message as this impact the performance in every form load.
8. Use Common SDK method
Using common methods are significantly faster than using the Execute method with the corresponding request message.
Use | Don’t Use |
Create | CreateRequest |
Retrieve | RetrieveRequest |
Update | UpdateRequest |
Delete | DeleteRequest |
RetrieveMultiple | RetrieveMultipleRequest |
9. Adjust Proxy setting in Client Browser
While the Microsoft Dynamics CRM server (on-premise) is installed, we should bypass the proxy server to achieve better throughput resulting better performance. The server offers a local web address that requires no proxy to be reached bypassing the proxy. You should select Bypass proxy server for local addresses and provide the fully qualified domain name of the Microsoft Dynamics CRM server in the exceptions list.
This gives better throughput when records are created by using the Microsoft Dynamics CRM SDK. This has to be configured during CRM installation in server and adjusting proxy in client machine.
10. Improve service channel allocation
We can establish a connection to the Microsoft Dynamics CRM web services and authenticate users by using the OrganizationServiceProxy and DiscoveryServiceProxy service proxy classes using CRM SDK. However, improper use of these service proxy classes can reduce performance. Therefore, if you understand when and how to use the different client classes that are available in the SDK, you can often obtain better application performance.
When we establish a Windows Communication Foundation (WCF) service channel by using a service endpoint, for example, by using the organization web service, our application must perform two time consuming operations:
- Metadata download from the endpoint
- User authentication.
We can improve performance if our application performs these operations a minimum number of times for each application session. The OrganizationServiceProxy constructor shown here performs both these operations any time a service proxy object is created.
OrganizationServiceProxy (Uri uri, Uri homeRealmUri, ClientCredentials clientCredentials, ClientCredentials deviceCredentials)
You typically obtain better performance if your application uses this constructor to create an instance of the service proxy by using this constructor one time during the application session and cache the returned reference for use in different code paths within your application. Notice that the returned service reference is not thread safe so multi-threaded applications will need to allocate one instance per thread. Applications must also call Dispose on the service proxy object before they terminate in order to free service channel allocated resources.
The service proxy class performs the metadata download and user authentication by using the following class methods
IServiceManagement<IOrganizationService> orgServiceManagement = ServiceConfigurationFactory.CreateManagement<IOrganizationService>(new Uri(organizationUrl))AuthenticationCredentials authCredentials = orgServiceManagement.Authenticate(credentials)
The CreateManagement method performs the metadata download while the Authenticate method authenticates the user. The returned objects from these methods are thread safe and can be statically cached by your application. You can then use these objects to construct a service proxy object that uses one of the other available constructors.
OrganizationServiceProxy (orgServiceManagement, authCredentials.ClientCredentials)OrganizationServiceProxy (orgServiceManagement, authCredentials.SecurityTokenResponse)
By caching the service management and authenticated credential objects, your application can more efficiently construct the service proxy objects more than one time per application session. If you enable early-bound types onOrganizationServiceProxy through one of the EnableProxyTypes methods, you must do the same on all service proxies that are created from the cached IServiceManagement object. If your application uses the metadata, we recommend that it caches the metadata that it retrieves and periodically calls the RetrieveTimestampRequest message to determine whether it must refresh the cache.
In addition, monitor your WCF security token (Token) and refresh it before it expires so that you do not lose the token and have to start over with authentication. To check the token, create a custom class that inherits from theOrganizationServiceProxy or DiscoveryServiceProxy class and that implements the business logic to check the token. Or wrap the proxy classes in a new class. Another technique is to explicitly check the token before each call to the web service. Example code that demonstrates these techniques can be found in the ManagedTokenDiscoveryServiceProxy,ManagedTokenOrganizationServiceProxy, and AutoRefreshSecurityToken classes in the Helper code:
Most importantly, always call Dispose method for all web service objects which are disposable.
11. Minimize CRM Service Calls
When we write code sometimes we call CRM service many a times to achieve a single task. The strong recommendation here is to try all possible ways to minimise the no. of calls to CRM service.
These are the ways by which we can minimise the CRM service calls.
- Using variables to hold frequently used field values.
- Using common classes avoiding duplicate classes.
Hope this will help to all who are looking for a best CRM implementation. Please provide feedback for the article improve. I am still updating the list for better performance best practice. Experts are Welcome to add if any other item I have missed.