Asp.net mvc 5 web应用程序中CRM连接的最佳实践

Asp.net mvc 5 web应用程序中CRM连接的最佳实践,asp.net-mvc-5,connection,httprequest,dynamics-crm,dynamics-crm-365,Asp.net Mvc 5,Connection,Httprequest,Dynamics Crm,Dynamics Crm 365,很抱歉,如果这个问题有点过于宽泛,但如果这是一个关于基于ASP.NET MVC 5 Owin的应用程序的问题,默认连接到MSSQL服务器,我不会有这么困难的时间,但我们使用CRM作为我们的数据库 好的,正如我提到的,我正在开发ASP.NET MVC5应用程序,很难找到创建、保持打开和关闭Dynamics CRM 365连接的最佳做法 我发现了很多帖子和博客,但每个人都站在自己这边。 有人说,最好是使用语句在中打开新连接,这样就可以立即关闭(这听起来不错,但请求可能会很慢,因为每个请求都需要打开到

很抱歉,如果这个问题有点过于宽泛,但如果这是一个关于基于ASP.NET MVC 5 Owin的应用程序的问题,默认连接到MSSQL服务器,我不会有这么困难的时间,但我们使用CRM作为我们的数据库

好的,正如我提到的,我正在开发ASP.NET MVC5应用程序,很难找到创建、保持打开和关闭Dynamics CRM 365连接的最佳做法

我发现了很多帖子和博客,但每个人都站在自己这边。

有人说,最好是使用语句在
中打开新连接,这样就可以立即关闭(这听起来不错,但请求可能会很慢,因为每个请求都需要打开到CRM的新连接)。

有人说,最好在应用程序作用域上创建
singleton
对象,在应用程序生命周期中保持它的打开状态,并在每次请求时重用它

通常我会在一些简单的控制台应用程序中使用
OrganizationServiceProxy
,但在这种情况下,我不确定我应该使用
OrganizationServiceProxy
还是
CrmServiceClient
或其他什么

如果有人有或有类似的问题,任何提示都会很好

更新:

@尼科诺

我从下载SDK并使用此dll-s
Microsoft.Xrm.Sdk.dll
Microsoft.Crm.Sdk.Proxy.dll
Microsoft.Xrm.Tooling.Connector.dll
Microsoft.IdentityModel.Clients.ActiveDirectory.dll

你提到

Microsoft.CrmSdk.XrmTooling.corepassembly 8.2.0.5

如果我正确的话,这个nuget包使用我下载的官方程序集,或者这个包有一些修改

关于那个测试

验证试验

如果我做对了,无论我使用
using
语句,实现
Dispose()
方法,还是在应用程序的生命周期中只使用应用程序作用域上的静态类,我都会得到相同的实例(如果我使用默认设置
requireRenewanceInstance=false

为了代码的简单性,我通常创建一个静态类(也可以使用单例,但通常过于简单)来返回CrmServiceClient对象。这样,我的代码就不会被新的CrmServiceClient调用所干扰,如果我想更改任何关于如何建立连接的内容

所以,在应用程序作用域上创建在应用程序生命周期内有效的静态类是一个好的实践吗?这意味着发出请求的每个用户都将使用相同的实例?这不是一个连接的性能问题吗

您的所有方法调用都将执行到完成或抛出异常,因此即使GC需要一段时间,也不会有打开的连接占用资源和/或阻止其他活动

这一节将我带回到另一节,在这一节中,我总是得到相同的
CrmServiceClient
实例,并得到xrm.tooling处理另一端缓存连接的部分,但在这一端发生了什么(web应用程序)。 与CRM的连接(即
CrmServiceClient
)不是非托管资源,我不应该显式地
Dispose()
它吗

我发现了一些使用
CrmServiceClient
的示例,几乎所有示例中
CrmServiceClient
都是使用
CrmServiceClient.OrganizationWebProxyClient
CrmServiceClient.OrganizationServiceProxy
ioorganizationservice
中铸造的

为什么会这样?这样做的好处是什么


我有很多问题,但这已经是我要问的问题了,有没有在线文档可以让我参考?

首先,我假设您使用的是Nuget最新的SDK DLL:Microsoft.CrmSdk.XrmTooling.corestassembly 8.2.0.5

我从未使用
语句将连接包装在
中,我想我从未见过这样做的示例。在我们有工具库之前的“旧时代”中有一些例子,其中创建
OrganizationServiceProxy
的调用被包装在使用
语句的
中,这导致许多没有经验的开发人员发布了带有连接性能问题的代码

幸运的是,我们已经通过Xrm.Tooling库修复了大部分问题

使用
CrmServiceClient
创建连接对象:

CrmServiceClient-crmSvc=new-CrmServiceClient(@“…连接字符串在这里…”)

现在,如果我创建了一个
OrganizationServiceContext
(或早期绑定的等效对象),我会使用
将其包装在
中,以便在我完成工作单元后确定对其进行处理

using (var ctx = new OrganizationServiceContext(crmSvc))
{
    var accounts = from a in ctx.CreateQuery("account")
                    select a["name"];

    Console.WriteLine(accounts.ToList().Count());
}
工具库为您处理连接通道和身份验证方面的所有其他问题。除非您指定每次创建一个新通道(通过在连接字符串中添加'RequireReneInstance=true'或在调用
new CrmServiceClient
时将
useUniqueInstance
设置为
true
),否则库将重用现有的已验证通道

我使用以下代码进行快速验证测试:

void Main()
{

    var sw = new Stopwatch();
    sw.Start();

    var crmSvc = GetCrmClient();

    Console.WriteLine($"Time to get Client # 1: {sw.ElapsedMilliseconds}");

    crmSvc.Execute(new WhoAmIRequest());

    Console.WriteLine($"Time to WhoAmI # 1: {sw.ElapsedMilliseconds}"); 

    var crmSvc2 = GetCrmClient();

    Console.WriteLine($"Time to get Client # 2: {sw.ElapsedMilliseconds}");

    crmSvc2.Execute(new WhoAmIRequest());

    Console.WriteLine($"Time to WhoAmI # 2: {sw.ElapsedMilliseconds}");    

}

public CrmServiceClient GetCrmClient()
{
    return new CrmServiceClient("...connection string goes here...");
}
当我使用
requireRenewanceInstance=true
运行此命令时,我得到以下控制台输出:

  • 是时候找客户了#1:2216
  • 时间到了#1:2394
  • 是时候得到客户了#2:4603
  • 时间到了#2:4780
显然,创建每个连接所用的时间大致相同

现在,如果我将其更改为
requirerenceinstance=false
(这是默认值),我将得到以下结果:

  • 是时候找客户了#1:3761
  • 时间到了#1:3960
  • 是时候找客户了#2:3961
  • 时间到了#2:4145
哇,这是一个很大的不同。发生了什么事?在第二次调用中,Xrm.Tooling库使用现有的服务通道和身份验证(缓存)
using (var crmSvc = GetCrmClient())
{
    Console.WriteLine($"Time to get Client # 1: {sw.ElapsedMilliseconds}");

    crmSvc.Execute(new WhoAmIRequest());

    Console.WriteLine($"Time to WhoAmI # 1: {sw.ElapsedMilliseconds}");
}

using (var crmSvc2 = GetCrmClient())
{
    Console.WriteLine($"Time to get Client # 2: {sw.ElapsedMilliseconds}");

    crmSvc2.Execute(new WhoAmIRequest());

    Console.WriteLine($"Time to WhoAmI # 2: {sw.ElapsedMilliseconds}");
}