关注本人微信和易信公众号: 微软动态CRM专家罗勇 ,回复256或者20170512可方便获取本文,同时可以在第一间得到我发布的最新的博文信息,follow me!我的网站是 www.luoyong.me 。
最近做代码审查,有个建议是Improve Microsoft Dynamics CRM service channel allocation performance的建议,请教了微软专家,Get了一下新技能,下面我做一次传声筒和翻译器,请听我讲来。
为了更好的看到效果,我这里使用了多个线程来凸显效果。我以前的项目,不在Dynamics 365中使用组织服务的话,一般都是每次查询会建立一次连接,代码类似如下:
using Microsoft.Xrm.Sdk; using Microsoft.Xrm.Sdk.Query; using Microsoft.Xrm.Tooling.Connector; using System; using System.ServiceModel; using System.Threading; namespace LuoYongLab { class Program { static void Main(string[] args) { try { for (var i = 0; i < 5; i++) { ThreadStart tStart = new ThreadStart(Work); Thread thread = new Thread(tStart); thread.Start(); } Console.WriteLine("程序运行完成!"); Console.ReadKey(); } catch (FaultException ex) { Console.WriteLine("程序出现异常:ex.Message=" + ex.Message); Console.ReadKey(); } } static void Work() { Console.WriteLine("线程开始" + DateTime.Now.ToLongTimeString() + ";线程ID:" + Thread.CurrentThread.ManagedThreadId); var crmSvc = new CrmServiceClient(new System.Net.NetworkCredential("[email protected]", "Pass", null), Microsoft.Xrm.Tooling.Connector.AuthenticationType.IFD, "demo.luoyong.me", "443", "demo", useUniqueInstance: false, useSsl: true); Console.WriteLine("线程ID: " + Thread.CurrentThread.ManagedThreadId + ";Token过期时间:" + crmSvc.OrganizationServiceProxy.SecurityTokenResponse.Response.Lifetime.Expires); if (crmSvc.IsReady) { QueryExpression qe = new QueryExpression("organization"); qe.ColumnSet = new ColumnSet("languagecode", "basecurrencyid"); EntityCollection ec = crmSvc.RetrieveMultiple(qe); if (ec.Entities.Count >= 1) { Console.WriteLine("线程ID: " + Thread.CurrentThread.ManagedThreadId + ";组织偏好语言:" + ec.Entities[0].GetAttributeValue<int>("languagecode")); } } Console.WriteLine("线程结束" + DateTime.Now.ToLongTimeString() + ";线程ID:" + Thread.CurrentThread.ManagedThreadId); } } }
效果如下,可以看到大概需要7秒钟。
我用fiddler抓包,你会发现每次认证都会下载元数据,一共下载了5次。
如果我改动代码如下:
using Microsoft.Xrm.Sdk; using Microsoft.Xrm.Sdk.Client; using Microsoft.Xrm.Sdk.Query; using System; using System.ServiceModel; using System.ServiceModel.Description; using System.Threading; namespace LuoYongLab { class Program { public static IServiceManagement<IOrganizationService> sm; static void Main(string[] args) { sm = ServiceConfigurationFactory.CreateManagement<IOrganizationService>(new Uri("https://demo.luoyong.me/XRMServices/2011/Organization.svc")); try { for (var i = 0; i < 5; i++) { ThreadStart tStart = new ThreadStart(Work); Thread thread = new Thread(tStart); thread.Start(); } Console.WriteLine("程序运行完成!"); Console.ReadKey(); } catch (FaultException ex) { Console.WriteLine("程序出现异常:ex.Message=" + ex.Message); Console.ReadKey(); } } static void Work() { ClientCredentials credentials = new ClientCredentials(); credentials.UserName.UserName = "[email protected]"; credentials.UserName.Password = "Pass"; Console.WriteLine("线程开始" + DateTime.Now.ToLongTimeString() + ";线程ID:" + Thread.CurrentThread.ManagedThreadId); OrganizationServiceProxy orgSvc = new OrganizationServiceProxy(sm, credentials); QueryExpression qe = new QueryExpression("organization"); qe.ColumnSet = new ColumnSet("languagecode", "basecurrencyid"); EntityCollection ec = orgSvc.RetrieveMultiple(qe); if (ec.Entities.Count >= 1) { Console.WriteLine("线程ID: " + Thread.CurrentThread.ManagedThreadId + ";组织偏好语言:" + ec.Entities[0].GetAttributeValue<int>("languagecode")); } Console.WriteLine("线程结束" + DateTime.Now.ToLongTimeString() + ";线程ID:" + Thread.CurrentThread.ManagedThreadId); } } }
我们可以看到执行时间也会缩短,从之前的大概需要7秒降低到需要1秒,速度提升不少。
我们看看Fiddler抓包效果,仅仅只有一次下载元数据,而且因为缓存执行的非常快。
在项目实战的话,我们可以在Application_Start的代码执行前面声明一个类似如下的全局静态变量:
public static IServiceManagement<IOrganizationService> sm;
然后在Application_Start的代码中进行类似如下初始化:
sm = ServiceConfigurationFactory.CreateManagement<IOrganizationService>(new Uri("https://demo.luoyong.me/XRMServices/2011/Organization.svc"));
最后在所有连接的地方就可以使用类似如下的代码进行连接了:
ClientCredentials credentials = new ClientCredentials(); credentials.UserName.UserName = "[email protected]"; credentials.UserName.Password = "Pass"; OrganizationServiceProxy orgSvc = new OrganizationServiceProxy(LuoYongApp.sm, credentials);