Dynamics CRM CrmServiceClient - 如何连接到多个组织?

时间:2018-02-17 15:43:13

标签: c# dynamics-crm

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

 CrmServiceClient conn = new CrmServiceClient(ConnectionString);

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

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

忽略新的连接字符串,并且连接仍保留在原始连接字符串中。这是由于连接池,我认为。

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

工作是什么设置" requireNewInstance=True"在两个连接字符串中。当我这样做时,Web应用程序能够在组织之间切换..但是Web应用程序的性能非常糟糕。每次加载< 1s之前加载的页面将加载30秒或更多时间,因为每次都是从新创建连接。

无论如何,有两个CrmServiceClient实例同时存活,连接到两个不同的CRM组织?或者有没有办法强制CrmServiceClent被处理和创建新的?

2 个答案:

答案 0 :(得分:3)

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实例,就可以执行以下操作:

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

个人意见:SDK中的CrmServiceClient文档记录很少,不清楚开发人员是如何使用它的。例如,处理多线程的正确方法是什么?它实现了IDisposable但是它实际上应该包含在using语句中吗?为什么要处理它,因为目的是维护跨工作单元的连接/身份验证。这只是令人困惑。即使RequireNewInstance似乎也很古怪。

效果说明:我不确定你为什么会遇到这么糟糕的表现。验证的时间不应超过几秒钟。这是我要研究的东西,因为它会导致生产问题,因为必须更新身份验证并且在页面加载期间可能会发生更新 - 导致偶尔的性能命中。例如,从我的本地机器运行时,设置两个CrmServiceClient对象的时间被测量为5-6秒。

答案 1 :(得分:0)

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

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