伍佰目录 短网址
  当前位置:海洋目录网 » 站长资讯 » 站长资讯 » 文章详细 订阅RssFeed

一种提升连接Dynamics 365性能的方法

来源:本站原创 浏览:92次 时间:2022-06-07

关注本人微信和易信公众号: 微软动态CRM专家罗勇 ,回复256或者20170512可方便获取本文,同时可以在第一间得到我发布的最新的博文信息,follow me!我的网站是 www.luoyong.me 。

 

最近做代码审查,有个建议是Improve Microsoft Dynamics CRM service channel allocation performance的建议,请教了微软专家,同事也参考了官方的文章:Best practices for developing with Dynamics 365 for Customer Engagement ,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("crmadmin@luoyong.me", "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次。

 

如果我改动代码如下,类 ManagedTokenOrganizationServiceProxy 代码来自Ali Sharifi 的文章 REFRESH SECURITY TOKEN FOR MICROSOFT DYNAMICS CRM CONNECTION ,但是我发现没什么用,因为 this._proxy.SecurityTokenResponse == null,所以我这里不会使用。

using Microsoft.Xrm.Sdk;using Microsoft.Xrm.Sdk.Client;using Microsoft.Xrm.Sdk.Query;using System;using System.Configuration;using System.ServiceModel;using System.Threading;namespace ConsoleApp{    class Program    {        public static IServiceManagement<IOrganizationService> sm;        public static AuthenticationCredentials authCredentials;        static void Main(string[] args)        {            sm = ServiceConfigurationFactory.CreateManagement<IOrganizationService>(new Uri(ConfigurationManager.AppSettings["orgUrl"]));            authCredentials = new AuthenticationCredentials();            authCredentials.ClientCredentials.UserName.UserName = ConfigurationManager.AppSettings["userName"];            authCredentials.ClientCredentials.UserName.Password = ConfigurationManager.AppSettings["passWord"];            authCredentials = sm.Authenticate(authCredentials);            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);            OrganizationServiceProxy orgSvc = new OrganizationServiceProxy(sm, authCredentials.ClientCredentials);            //OrganizationServiceProxy orgSvc = new OrganizationServiceProxy(sm, authCredentials.SecurityTokenResponse);            //ManagedTokenOrganizationServiceProxy orgSvc = new ManagedTokenOrganizationServiceProxy(sm, authCredentials.ClientCredentials);            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);        }    }}

 

 

using Microsoft.Xrm.Sdk;using Microsoft.Xrm.Sdk.Client;using System;using System.ServiceModel;using System.ServiceModel.Description;namespace ConsoleApp{    public sealed class ManagedTokenOrganizationServiceProxy : OrganizationServiceProxy    {        private AutoRefreshSecurityToken<OrganizationServiceProxy, IOrganizationService> _proxyManager;        public ManagedTokenOrganizationServiceProxy(Uri serviceUri, ClientCredentials userCredentials)            : base(serviceUri, null, userCredentials, null)        {            this._proxyManager = new AutoRefreshSecurityToken<OrganizationServiceProxy, IOrganizationService>(this);        }        public ManagedTokenOrganizationServiceProxy(IServiceManagement<IOrganizationService> serviceManagement,            SecurityTokenResponse securityTokenRes)            : base(serviceManagement, securityTokenRes)        {            this._proxyManager = new AutoRefreshSecurityToken<OrganizationServiceProxy, IOrganizationService>(this);        }        public ManagedTokenOrganizationServiceProxy(IServiceManagement<IOrganizationService> serviceManagement,            ClientCredentials userCredentials)            : base(serviceManagement, userCredentials)        {            this._proxyManager = new AutoRefreshSecurityToken<OrganizationServiceProxy, IOrganizationService>(this);        }        protected override void AuthenticateCore()        {            this._proxyManager.PrepareCredentials();            base.AuthenticateCore();        }        protected override void ValidateAuthentication()        {            this._proxyManager.RenewTokenIfRequired();            base.ValidateAuthentication();        }    }    ///<summary>    /// Class that wraps acquiring the security token for a service    /// </summary>    public sealed class AutoRefreshSecurityToken<TProxy, TService>        where TProxy : ServiceProxy<TService>        where TService : class    {        private TProxy _proxy;        ///<summary>        /// Instantiates an instance of the proxy class        /// </summary>        /// <param name="proxy">Proxy that will be used to authenticate the user</param>        public AutoRefreshSecurityToken(TProxy proxy)        {            if (null == proxy)            {                throw new ArgumentNullException("proxy");            }            this._proxy = proxy;        }        ///<summary>        /// Prepares authentication before authenticated        /// </summary>        public void PrepareCredentials()        {            if (null == this._proxy.ClientCredentials)            {                return;            }            switch (this._proxy.ServiceConfiguration.AuthenticationType)            {                case AuthenticationProviderType.ActiveDirectory:                    this._proxy.ClientCredentials.UserName.UserName = null;                    this._proxy.ClientCredentials.UserName.Password = null;                    break;                case AuthenticationProviderType.Federation:                case AuthenticationProviderType.LiveId:                    this._proxy.ClientCredentials.Windows.ClientCredential = null;                    break;                default:                    return;            }        }        ///<summary>        /// Renews the token (if it is near expiration or has expired)        /// </summary>        public void RenewTokenIfRequired()        {            if (null != this._proxy.SecurityTokenResponse &&            DateTime.UtcNow.AddMinutes(15) >= this._proxy.SecurityTokenResponse.Response.Lifetime.Expires)            {                try                {                    this._proxy.Authenticate();                }                catch (CommunicationException)                {                    if (null == this._proxy.SecurityTokenResponse ||                        DateTime.UtcNow >= this._proxy.SecurityTokenResponse.Response.Lifetime.Expires)                    {                        throw;                    }                }            }        }    }}

 

我们可以看到执行时间也会缩短,从之前的大概需要7秒降低到需要1秒,速度提升不少。

 

我们看看Fiddler抓包效果,仅仅只有一次下载元数据,而且因为缓存执行的非常快。

 

如果要缓存的话,我这里在Application Start事件时候缓存代码如下,当然要添加对 System.Runtime.Caching 的引用。

using System.Runtime.Caching;            ObjectCache cache == =<IOrganizationService> sm = ServiceConfigurationFactory.CreateManagement<IOrganizationService>( Uri(ConfigurationManager.AppSettings[= = ConfigurationManager.AppSettings[= ConfigurationManager.AppSettings[, sm.Authenticate(authCredentials), policy);

 

然后在代码中获取组织服务就用如下代码:

using System.Runtime.Caching;ObjectCache cache ==  OrganizationServiceProxy(((IServiceManagement<IOrganizationService>)cache[]), ((AuthenticationCredentials)cache[]).ClientCredentials);

 


  推荐站点

  • At-lib分类目录At-lib分类目录

    At-lib网站分类目录汇集全国所有高质量网站,是中国权威的中文网站分类目录,给站长提供免费网址目录提交收录和推荐最新最全的优秀网站大全是名站导航之家

    www.at-lib.cn
  • 中国链接目录中国链接目录

    中国链接目录简称链接目录,是收录优秀网站和淘宝网店的网站分类目录,为您提供优质的网址导航服务,也是网店进行收录推广,站长免费推广网站、加快百度收录、增加友情链接和网站外链的平台。

    www.cnlink.org
  • 35目录网35目录网

    35目录免费收录各类优秀网站,全力打造互动式网站目录,提供网站分类目录检索,关键字搜索功能。欢迎您向35目录推荐、提交优秀网站。

    www.35mulu.com
  • 就要爱网站目录就要爱网站目录

    就要爱网站目录,按主题和类别列出网站。所有提交的网站都经过人工审查,确保质量和无垃圾邮件的结果。

    www.912219.com
  • 伍佰目录伍佰目录

    伍佰网站目录免费收录各类优秀网站,全力打造互动式网站目录,提供网站分类目录检索,关键字搜索功能。欢迎您向伍佰目录推荐、提交优秀网站。

    www.wbwb.net