简体   繁体   English

如何防止 Dynamics 365 在每次建立 CrmServiceClient 连接时进行身份验证

[英]How to prevent that Dynamics 365 authenticates every time a CrmServiceClient connection is made

We are in the process of migrating from Dynamics on-prem to Dynamics 365 online.我们正在从 Dynamics on-Prem 迁移到 Dynamics 365 online。 So we had to change also a webapp that is connecting to Dynamics.因此,我们还必须更改连接到 Dynamics 的 web 应用程序。

The webapp is still working but the performance is poor. webapp 仍在工作,但性能很差。 We started to do some traces to see why.我们开始做一些跟踪以了解原因。 In this trace we saw that the app is doing for a single request different calls to Dynamics online.在此跟踪中,我们看到应用程序正在针对单个请求执行对 Dynamics 的不同在线调用。 Reason for this is that we are indeed retrieving different sets of data.原因是我们确实在检索不同的数据集。 But we are surprised to see that authentication is done also multiple times.但我们惊讶地发现身份验证也进行了多次。 This authentication is slowing down the response from dynamics.这种身份验证减慢了动态响应。 We were expecting that authentication was done only with the first request.我们期望仅对第一个请求进行身份验证。

The code I'm using to make the connection is in an abstract class that is instantiated by different other classes.我用来建立连接的代码在一个抽象的 class 中,由不同的其他类实例化。 This classes are using the following property returning a CrmServiceClient from the namespace Microsoft.Xrm.Tooling.Connector:此类使用以下属性,从命名空间 Microsoft.Xrm.Tooling.Connector 返回 CrmServiceClient:

     protected CrmServiceClient CustomCrmServiceProxy
    {
        get
        {
            CrmServiceClient client = new CrmServiceClient(CrmConnection.Connectionstring);
            client.CallerId = GetCallerId();

            return client;
        }
    }

The connectionstring is AuthType=ClientSecret;url={0};ClientId={1};ClientSecret={2};连接字符串是 AuthType=ClientSecret;url={0};ClientId={1};ClientSecret={2}; with the values replaced.替换了值。

In the classes using the abstract class we are calling the property like在使用抽象 class 的类中,我们将属性称为

var data = this.CustomCrmServiceProxy.RetrieveMultiple("fetch xml");

Important is that we are passing the callerid to the CrmServiceClient and this one can be different when the visitor switch to a page in another language.重要的是我们将 callerid 传递给 CrmServiceClient,当访问者切换到另一种语言的页面时,这个可能会有所不同。

Is there a way to prevent the multiple authentication?有没有办法防止多重身份验证? Is implementing a singleton pattern an option?实施 singleton 模式是一种选择吗? But what with the different callerids in that case?但是在那种情况下,不同的 callerid 怎么办? And is there maybe a good example for CrmServiceClient? CrmServiceClient 是否有一个很好的例子?

Can you try something like this?你可以试试这样的东西吗?

This would create a single instance of the connection (with the callerID) and then just continually refer to that instance.这将创建连接的单个实例(带有 callerID),然后不断地引用该实例。

CrmServiceClient _client = null;

protected CrmServiceClient CustomCrmServiceProxy
{
  get
  {
    if (_client == null)
    {
        _client = new CrmServiceClient(CrmConnection.Connectionstring);
        _client.CallerId = GetCallerId();
    }
    return _client;
}

The CrmServiceClient offers a number of constructors giving the opportunity to reuse a connection instance. CrmServiceClient提供了许多构造函数,提供了重用连接实例的机会。

Eg the following constructor overload has parameter useUniqueInstance .例如,以下构造函数重载具有参数useUniqueInstance Pass a false value to it when a cached instance should be used.当应该使用缓存实例时,将false值传递给它。

public CrmServiceClient(string userId, SecureString password, string domain, string homeRealm, string hostName, string port, string orgName, bool useUniqueInstance = false, bool useSsl = false, OrganizationDetail orgDetail = null)

In most cases however a web app will be consumed by multiple clients, often concurrently, and a singleton connection object would not scale well in those scenarios.然而,在大多数情况下,web 应用程序将被多个客户端使用,通常是同时使用,并且 singleton 连接 object 在这些情况下无法很好地扩展。 In these cases you can introduce a connection pool .在这些情况下,您可以引入连接池

A connection pool class would be responsible for maintaining a collection of CrmServiceClient instances.连接池 class 将负责维护CrmServiceClient实例的集合。 A factory pattern could be used to claim instances from the pool object.工厂模式可用于从池 object 中声明实例。 When disposed, the factory instance returns all claimed instances to the pool.释放后,工厂实例将所有声明的实例返回到池中。

Your factory class could implement the existing IOrganizationServiceFactory .您的工厂 class 可以实现现有的IOrganizationServiceFactory This interface is designed with impersonation requirements in mind.此界面的设计考虑了模拟要求。

Note: do not make classes that currently use CrmServiceClient connections responsible for creating these instances.注意:不要让当前使用CrmServiceClient连接的类负责创建这些实例。 Instead inject IOrganizationServiceFactory or IOrganizationService objects into the constructors of these classes.而是将IOrganizationServiceFactoryIOrganizationService对象注入到这些类的构造函数中。

I have seen situations where a program executes a get accessor more times than I think it should.我见过程序执行get访问器的次数比我认为的要多的情况。

Rather than having it as a property, I'd say try making it a method.与其将其作为属性,我会说尝试将其作为方法。

protected CrmServiceClient GetService()
{
    var client = new CrmServiceClient(CrmConnection.Connectionstring);
    client.CallerId = GetCallerId();
    return client;
}

Then, one option for lazy instantiation would be:然后,延迟实例化的一种选择是:

private CrmServiceClient _svc;
private CrmServiceClient svc => _svc ?? (_svc = GetService());

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM