am sorry if this question will be a bit to broad but if this is question about normal ASP.NET MVC 5 Owin based application with default connection to MSSQL server i would not have such hard time but we use CRM as our database.
Ok as i mention am working on ASP.NET MVC5 application and am having hard time finding what is the best practice to create, keep open and to close connection to Dynamics CRM 365?
I found some many posts and blogs but everyone pulling on his side of the road.
Some say it's better for every request to open new connection in using
statement so it could be closed right away (that's sounds good but it's a possible that requests will be slow because on every request it needs to open new connection to CRM).
Some say it' better to make singleton
object on application scope, keep it open during application lifetime and reuse it on every request.
Normally i would use OrganizationServiceProxy
in some simple console app but in this case am not sure should i use OrganizationServiceProxy
or CrmServiceClient
or something else?
If anyone have or had some similar problem, any hint would be great.
UPDATE:
@Nicknow
I downloaded SDK from SDK 365 and am using this dll-s. Microsoft.Xrm.Sdk.dll
, Microsoft.Crm.Sdk.Proxy.dll
, Microsoft.Xrm.Tooling.Connector.dll
and Microsoft.IdentityModel.Clients.ActiveDirectory.dll
.
You mention
Microsoft.CrmSdk.XrmTooling.CoreAssembly 8.2.0.5.
if am correct this nuget package use official assembly that i downloaded, or there are some modification to this package?
About that test
proof test
if i got it right, no matter if i use using
statement, implement Dispose()
method or just use static class on application scope for a lifetime of application i will allways get same instance (If i use default settings RequireNewInstance=false
)?
For code simplicity, I usually create a static class (a singleton could be used too, but would usually be overkill) to return a CrmServiceClient object. That way my code is not littered with new CrmServiceClient calls should I want to change anything about how the connection is being made.
So it would be good practice to create static class on application scope that lives for application lifetime? That means that every user that makes request would use same instance ? Wouldn't that be i performance issue for that one connection?
All of your method calls will execute to completion or throw an exception thus even if the GC takes a while there is no open connection sitting out there eating up resources and/or blocking other activity.
This one takes me back to section where i allways get same instance of CrmServiceClient
and got the part that xrm.tooling handles cached connection o the other side but what happens on this side (web application).
Isn't the connection to CRM (i.e. CrmServiceClient
) unmanaged resources, shouldn't i Dispose()
it explicitly?
I found some examples with CrmServiceClient
and pretty much in all examples CrmServiceClient
is casted in IOrganizationService
using CrmServiceClient.OrganizationWebProxyClient
or CrmServiceClient.OrganizationServiceProxy
.
Why is that and what are the benefits of that?
I got so many questions but this is already allot to ask, is there any online documentation that you could point me to it?
First, I'm assuming you are using the latest SDK DLLs from Nuget: Microsoft.CrmSdk.XrmTooling.CoreAssembly 8.2.0.5.
I never wrap the connection in a using
statement and I don't think I've ever seen an example where that is done. There are examples from the "old days", before we had tooling library, where calls to create OrganizationServiceProxy
were wrapped in a using
statement, which caused a lot of inexperienced developers to release code with connection performance issues.
Luckily most of this has been fixed for us through the Xrm.Tooling library.
Create your connection object using CrmServiceClient
:
CrmServiceClient crmSvc = new CrmServiceClient(@"...connection string goes here...");
Now if I create an OrganizationServiceContext
(or an early-bound equivalent) object I do wrap that in a using
so that it is determinedly disposed when I've completed my unit of work.
using (var ctx = new OrganizationServiceContext(crmSvc))
{
var accounts = from a in ctx.CreateQuery("account")
select a["name"];
Console.WriteLine(accounts.ToList().Count());
}
The Xrm.Tooling library handles everything else for you as far the connection channel and authentication. Unless you specify to create a new channel each time (by adding 'RequireNewInstance=true' to the connection string or setting the useUniqueInstance
to true
when calling new CrmServiceClient
) the library will reuse the existing authenticated channel.
I used the following code to do a quick proof test:
void Main()
{
var sw = new Stopwatch();
sw.Start();
var crmSvc = GetCrmClient();
Console.WriteLine($"Time to get Client # 1: {sw.ElapsedMilliseconds}");
crmSvc.Execute(new WhoAmIRequest());
Console.WriteLine($"Time to WhoAmI # 1: {sw.ElapsedMilliseconds}");
var crmSvc2 = GetCrmClient();
Console.WriteLine($"Time to get Client # 2: {sw.ElapsedMilliseconds}");
crmSvc2.Execute(new WhoAmIRequest());
Console.WriteLine($"Time to WhoAmI # 2: {sw.ElapsedMilliseconds}");
}
public CrmServiceClient GetCrmClient()
{
return new CrmServiceClient("...connection string goes here...");
}
When I run this with RequireNewInstance=true
I get the following console output:
Clearly it was taking about the same amount of time to create each connection.
Now, if I change it to RequireNewInstance=false
(which is the default) I get the following:
Wow, that's a big difference. What is going on? On the second call the Xrm.Tooling library uses the existing service channel and authentication (which it cached.)
You can take this one step further and wrap your new CrmServiceClient
calls in a using
and you'll get the same behavior, because disposing of the return instanced does not destroy the cache.
So this will return times similar to above:
using (var crmSvc = GetCrmClient())
{
Console.WriteLine($"Time to get Client # 1: {sw.ElapsedMilliseconds}");
crmSvc.Execute(new WhoAmIRequest());
Console.WriteLine($"Time to WhoAmI # 1: {sw.ElapsedMilliseconds}");
}
using (var crmSvc2 = GetCrmClient())
{
Console.WriteLine($"Time to get Client # 2: {sw.ElapsedMilliseconds}");
crmSvc2.Execute(new WhoAmIRequest());
Console.WriteLine($"Time to WhoAmI # 2: {sw.ElapsedMilliseconds}");
}
For code simplicity, I usually create a static class (a singleton could be used too, but would usually be overkill) to return a CrmServiceClient
object. That way my code is not littered with new CrmServiceClient
calls should I want to change anything about how the connection is being made.
To fundamentally answer the question about using
, we don't need to use it because there is nothing to be released. All of your method calls will execute to completion or throw an exception thus even if the GC takes a while there is no open connection sitting out there eating up resources and/or blocking other activity.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With