【问题标题】:Dynamics CRM CrmServiceClient - how to connect to multiple organisations?Dynamics CRM CrmServiceClient - 如何连接到多个组织?
【发布时间】:2018-07-28 07:42:08
【问题描述】:

我有一个 ASP.Net Web 应用程序,它使用 XRM Tooling Connector 连接到 Dynamics CRM。我传入一个连接字符串并像这样创建连接:

 CrmServiceClient conn = new CrmServiceClient(ConnectionString);

如果我连接到一个 Dynamics CRM 组织,这很好用。但是,如果我想更改 ASP.Net 应用程序中的连接,并使用不同的连接字符串调用服务客户端

CrmServiceClient conn = new CrmServiceClient(ConnectionString**2**);

新的连接字符串被忽略,连接保持原来的连接字符串。我认为这是由于连接池造成的。

如果我在设置连接字符串之前调用conn.Dispose() - 这没有区别。

有效的是在两个连接字符串中设置“requireNewInstance=True”。当我这样做时,Web 应用程序能够在组织之间切换……但是 Web 应用程序的性能很糟糕。之前需要

是否有两个 CrmServiceClient 实例同时处于活动状态,连接到两个不同的 CRM 组织?或者有什么方法可以强制释放 CrmServiceClent 并创建新的?

【问题讨论】:

    标签: c# dynamics-crm


    【解决方案1】:

    CrmServiceClient 不处理缓存多个连接字符串的连接。您需要自己处理缓存部分。除非你有一个不受限制的列表,否则这通常可以通过两个对象来处理。

    var org1SvcClient = new CrmServiceClient(org1ConnString);
    var org2SvcClient = new CrmServiceClient(org2ConnString);
    

    只要您将RequireNewInstance=true 作为每个连接字符串的一部分,您就会有两个不同的对象指向两个不同的组织。

    如果您有很多连接字符串,您可能希望使用字典来缓存它们,这样您就可以通过连接字符串文本简单地引用它们来获取正确的对象。

    这是一个这样的缓存类应该是什么样子的快速示例:

    public static class CrmServiceClientCache
    {
        private static Dictionary<string, CrmServiceClient> _internalCache = new Dictionary<string, CrmServiceClient>();
    
        private static Object _objLock = new object();
    
        public static CrmServiceClient Get(string connectionString)
        {
            if (_internalCache.ContainsKey(connectionString)) return _internalCache[connectionString];
            else
            {
                lock (_objLock)
                {
                    if (!_internalCache.ContainsKey(connectionString) && _internalCache[connectionString] != null)
                    {
                        var svcClient = new CrmServiceClient(connectionString);
                        if (svcClient.IsReady) _internalCache[connectionString] = svcClient;
                        else throw new Exception($"Failed to Successfully Create CrmServiceClient: {svcClient.LastCrmError}", svcClient.LastCrmException);
                    }
                    return _internalCache[connectionString];
                }
            }
        }
    }
    

    然后在您的代码中,只要您想要一个特定连接字符串的 CrmServiceClient 实例,您就可以执行以下操作:

    现在您可以从代码中的任何位置调用“CrmServiceClientCache.Get(org1ConnString)”,而不必担心它是否已被实例化。如果没有,则将实例化并返回一个新对象。如果已实例化,则返回现有对象。

    个人意见CrmServiceClient 在 SDK 中的记录很差,不清楚它打算如何被开发人员使用。例如,处理多线程的正确方法是什么?它实现了IDisposable,但它实际上应该包含在using 语句中吗?以及为什么要处理它,因为目的是保持跨工作单元的连接/身份验证。这只是令人困惑。甚至RequireNewInstance 看起来也很古怪。

    性能说明:我不确定您为什么会得到如此糟糕的性能。进行身份验证的时间不应超过几秒钟。这是我会研究的东西,因为它会导致生产问题,因为必须更新身份验证并且更新可能会在页面加载期间发生 - 导致偶尔的性能下降。例如,从我的本地计算机运行设置两个 CrmServiceClient 对象的时间约为 5-6 秒。

    【讨论】:

    • 非常丰富的答案,我将进一步调查。我认为 30 秒页面加载的原因是因为这个特定页面对 Dynamics 进行了多次调用,在连接保持打开之前,现在它在每次调用时打开,每次都执行身份验证请求,RequireInstance=True
    • 知道了,是的,这很容易做到。我会在页面加载过程中重用CrmServiceClient,这可能会使您的性能达到更可接受的水平。
    【解决方案2】:

    我同意 Nicknow 关于性能说明的观点,我们将 V3.0.0.0 Microsoft.Xrm.Tooling.Connector 与 CRM Dynamics 360 一起使用,当我们跨越多个组织时,我们看不到任何性能问题,而不是 1 ,2,3。我们上升到 1.2.3.....14。

    我对处置也有类似的疑问。 一个建议是,最好在每次请求后删除 svcClient。原因是如果令牌过期(CRM 不会提醒您),您的程序将出现一些错误异常。重复使用它是好的,但如果令牌过期,就不可能了。或者您需要读取值“Token ValidFrom”和“Token ValidTo”是否有效 = True。所以你需要构建你的自定义连接池逻辑,这很好。否则在请求完成后将其从缓存中删除。

    【讨论】:

      猜你喜欢
      • 2017-12-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-03
      • 1970-01-01
      • 1970-01-01
      • 2016-10-06
      相关资源
      最近更新 更多