6

I am currently going through the process of upgrading our product CRM SDK and the main change I have encountered is that instead of connecting to the Xrm service and creating my IOrganizationService using the tried and trusted method of:

var connection = CrmConnection.Parse(connectionString);
var service = new OrganizationService(connection);

I am now having to utilise the CrmServiceClient from the Tooling namespace:

 CrmServiceClient conn = new Microsoft.Xrm.Tooling.Connector.CrmServiceClient(connectionString).OrganizationServiceProxy;

Now this is all fine except from one major issue...memory.

Using the older Xrm.Client method you were able to specify the Service Configuration Instance Mode (which defaulted to ServiceConfigurationInstanceMode.PerName). What this meant is that the service was reused if the same application called the create multiple times. This kept the memory footprint low. The below image show the amount of allocated memory after calling to create a service instance 100 times

enter image description here

However, using the newer method you cannot set this instance mode anywhere and it seems that a brand new connection is created every time whether you want it or not. Here are the results of the same test: enter image description here

As you can see, with every new connection, more and more memory is allocated. I can;t see anywhere that i can tell it to reuse the service.

So what I'm basically asking is, am I going about this in the wrong way? Should I be creating and caching everything myself? Are there hidden classes/methods that I am missing? Any help would be greatly appreciated.

doodlleus
  • 575
  • 4
  • 14
  • what is fulle code / setting and what is the new version of XRM SDK? do you cache the connection – lordkain Nov 28 '16 at 16:01
  • The only pertinent code is what i have shown above. What else would you need? I am not caching anything as I have never needed to do so with the xrm.client way of connecting. the newer SDK is verion 8.2.0 of Microsoft.CrmSdk.CoreAssemblies (the namespace is shown above) – doodlleus Nov 28 '16 at 16:04
  • You aren't doing anything wrong, as from 2016 that is the new way to setup connections like I was doing in [FakeXrmEasy](https://github.com/jordimontana82/fake-xrm-easy/blob/master/FakeXrmEasy.Shared/XrmRealContext.cs#L67-L77), so it looks like a memory leak in the tooling assembly. What if you cache the connection yourself? Any major benefits? – Jordi Nov 28 '16 at 17:12
  • 2
    One thing ive noticed is that, regardless of whether you set "RequireNewInstance" on the connection string to true or false, dissassembling the library shows that it ignores the setting and hardcodes it if you are initializing the client using a connectionstring... – doodlleus Nov 28 '16 at 17:50
  • 1
    @doodlleus: You seem to have found the explanation. I have worked with many versions (well, actually all versions) of the CRM SDK and my experience is that the tools provided with it appeared to be of varying quality. Often known bugs can be found not being solved for years. Possibly the `CrmServiceClient` was designed and tested with single user apps (e.g. for phones) kept in mind. I hope some day Microsoft will make the SDK open source on GitHub, so we can submit our fixes. – Henk van Boeijen Nov 29 '16 at 22:02
  • Looks like the latest SDK 8.2.0.1 "fixes" RequireNewInstance so that by default your existing connection is reused, but passing "RequireNewInstance=true" will create a new connection. What's a little goofy is the cache key is hardcoded to a static string, so if you don't pass "RequireNewInstance=true" but keep newing up CrmServiceClient with unique connection strings, they'll all use the first connection. – Matt Dearing Dec 15 '16 at 20:03
  • How did you resolve this? I know it's a very old post but we are seeing the same issue with the Dynamics Online/Datavverse API and Microsoft will soon deprecate the WS-Trust API, that means the only option is to use the CrmServiceClient. Do you have any detail on how you solved this? – Juan Stoppa Feb 17 '22 at 20:50

1 Answers1

2

The latest SDK (8.2.0.1) caches and resuses the connection as long as the connectionstring does not inclue RequireNewInstance=true.

One thing worth noting is even if you new up another CrmServiceClientwith a unique connection string (pointing to a different CRM organization), but the connection string does not include RequireNewInstance=true, the CrmServiceClient will reuse the previous cached connection.

So

var connectionString = $@"Url=https://ORG1.crm.dynamics.com;AuthType=Office365;UserName=USER@DOMAIN.com;Password=PASSWORD";
var connectionString2 = $@"Url=https://ORG2.crm.dynamics.com;AuthType=Office365;UserName=USER@DOMAIN.com;Password=PASSWORD";       

var crmSvcClient = new CrmServiceClient(connectionString);
((WhoAmIResponse)crmSvcClient.Execute(new WhoAmIRequest())).OrganizationId.Dump();
crmSvcClient.ConnectedOrgFriendlyName.Dump();

var crmSvcClient2 = new CrmServiceClient(connectionString2);
((WhoAmIResponse)crmSvcClient2.Execute(new WhoAmIRequest())).OrganizationId.Dump();
crmSvcClient2.ConnectedOrgFriendlyName.Dump();

Prints out the guid and ORG1 friendly name both times. If you pass RequireNewInstance=true in connectionstring2 then you will see ORG2 printed out.

Matt Dearing
  • 9,286
  • 1
  • 23
  • 25