I was dealing with
performance issues in WCF services which was using Microsoft Dynamic CRM SDK
for basic CRUD operations.
Approach 1 – Never make your OrganizationServiceProxy as Static
I created a class
variable of OrganizationProxy as static and every time the
request come it is shared between multiple requests as that the property of a
Static variable.
private static OrganizationServiceProxy
_serviceProxy;
public static OrganizationServiceProxy OrganizationServiceProxy
{
get
{
if (_serviceProxy == null)
{
string crmUrl = ConfigurationManager.AppSettings["crmUrl"];
ClientCredentials creds = new ClientCredentials();
creds.Windows.ClientCredential = new System.Net.NetworkCredential(
ConfigurationManager.AppSettings["Username"],
ConfigurationManager.AppSettings["password"],
ConfigurationManager.AppSettings["Domain"]);
_serviceProxy = new OrganizationServiceProxy(new
Uri(crmUrl), null, creds, null);
_serviceProxy.EnableProxyTypes();
}
return _serviceProxy;
}
}
Definitely above solution
resulted in enormous performance improvement.
But it also resulted in
poisoning of OrganizationProxy and CRM Connection. I would like to explain
poisoning of proxy with below diagram.
An Ideal and expected scenario is whoever is creating an opportunity, CREATEDBY and OWNER field in CRM should be populated under his/her name as a Sales representative.
But what had happened,
when WCF service was hit by multiple and parallel requests it has used the
existing Organization Proxy to create an opportunity in CRM with some other
user credentials.
Here Opportunity C and D
are getting created under Rose instead D should be created under – Manager. (Probably that’s why he is angry :P)
Now, how to improve performance
and to deal with the underline poisoning problem.
Solution-2: Make only
Metadata Static and used in while creating OrganizationServiceProxy.
[ThreadStatic]
private static IServiceManagement<IOrganizationService>
_ManagementService;
//Next
step is to define the get method for this variable
public static OrganizationServiceProxy ManagementService
{
get
{
string crmUrl = ConfigurationManager.AppSettings["crmUrl"];
if (_ManagementService == null)
{
// Here we are
creating Connection with only Metadata information about CRM,
// which is
quite heavy when making CRM Connections.
IServiceManagement<IOrganizationService>
ManagementServiceLocal =
ServiceConfigurationFactory.CreateManagement(new Uri(crmUrl));
//
Observe NO Credentials being passed.
_ManagementService = ManagementServiceLocal;
}
ClientCredentials creds = new ClientCredentials();
creds.Windows.ClientCredential = new System.Net.NetworkCredential(
ConfigurationManager.AppSettings["Username"],
ConfigurationManager.AppSettings["password"],
ConfigurationManager.AppSettings["Domain"]);
// Here we are
combining Management Instance and User Credentails
// to create
the Organization Proxy for doing CRUD Operation in CRM.
OrganizationServiceProxy serviceProxy = new OrganizationServiceProxy(_ManagementService,
creds);
serviceProxy.EnableProxyTypes();
return serviceProxy;
}
}
The OrganizationServiceProxy has
an overloaded constructor method which can accept metadata as in parameter when
creating organization proxy.
So we can cache Management Instance only which help us gaining performance and next we can always create a fresh Organization Proxy with user credentials passing cached management service instance and this would avoid any poisoning of service Proxy.
Try this solution in
your environment and let me know if it work and how much performance you gain.
Happy CRMing.