很抱歉,如果这个问题有点广泛,但如果这是关于普通的ASP.NET MVC 5基于Owin的应用程序与MSSQL服务器的默认连接的问题我不会有这么难,但我们使用CRM作为我们的数据库.
好的,我提到我正在研究ASP.NET MVC5应用程序,并且很难找到创建的最佳实践,保持打开并关闭与Dynamics CRM 365的连接?
我发现了很多帖子和博客,但每个人都在他的路上.
有人说每个请求在using
语句中打开新连接更好,所以它可以立即关闭(这听起来不错但是请求可能会很慢,因为在每次请求时都需要打开与CRM的新连接).
有人说最好singleton
在应用程序范围内创建对象,在应用程序生命周期内保持打开,并在每个请求上重用它.
通常我会用OrganizationServiceProxy
一些简单的控制台应用程序,但在这种情况下,我不知道我应该使用OrganizationServiceProxy
或者CrmServiceClient
还是其他什么东西?
如果有人有或有类似的问题,任何提示都会很棒.
更新:
@Nicknow
我从SDK 365下载了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.CoreAssembly 8.2.0.5.
如果我正确这个nuget包使用我下载的官方程序集,或者对这个程序包有一些修改?
关于那个测试
验证测试
如果我做对了,无论我是否使用using
语句,实现Dispose()
方法或只是在应用程序范围内使用静态类一生的应用程序我将总是获得相同的实例(如果我使用默认设置RequireNewInstance=false
)?
为了简化代码,我通常会创建一个静态类(也可以使用单例,但通常是矫枉过正)来返回CrmServiceClient对象.这样我的代码就不会出现新的CrmServiceClient调用,我想改变关于如何建立连接的任何内容.
那么在适用于应用程序生命周期的应用程序范围上创建静态类是一个好习惯吗?这意味着发出请求的每个用户都会使用相同的实例?那不是那个连接的性能问题吗?
所有方法调用都将执行完成或抛出异常,因此即使GC需要一段时间没有开放连接,因此会占用资源和/或阻止其他活动.
这个让我回到我总是获得相同实例CrmServiceClient
的部分,并得到了xrm.tooling处理缓存连接的部分,但另一方面却发生了什么(Web应用程序).是不是与CRM(即CrmServiceClient
)非托管资源的连接,我不应该Dispose()
明确吗?
我发现了一些例子有CrmServiceClient
,并在所有的例子几乎CrmServiceClient
在铸造IOrganizationService
使用CrmServiceClient.OrganizationWebProxyClient
或CrmServiceClient.OrganizationServiceProxy
.
为什么会这样,有什么好处呢?
我有很多问题,但这已经分配了问题,是否有任何在线文档可以指向我?
1> Nicknow..:
首先,我假设你使用的是最新的SDK的DLL从的NuGet:Microsoft.CrmSdk.XrmTooling.CoreAssembly 8.2.0.5.
我从来没有在一个using
声明中包含连接,我认为我从未见过这样做的例子.在我们拥有工具库之前,有一些来自"旧时代"的例子,其中对create的调用OrganizationServiceProxy
被包装在一个using
语句中,这导致许多没有经验的开发人员发布具有连接性能问题的代码.
幸运的是,大部分内容都是通过Xrm.Tooling库为我们修复的.
使用CrmServiceClient
以下方法创建连接对象
CrmServiceClient crmSvc = new CrmServiceClient(@"...connection string goes here...");
现在,如果我创建一个OrganizationServiceContext
(或一个早期绑定的等价物)对象,我using
会将其包装成一个,以便在我完成我的工作单元时确定它.
using (var ctx = new OrganizationServiceContext(crmSvc))
{
var accounts = from a in ctx.CreateQuery("account")
select a["name"];
Console.WriteLine(accounts.ToList().Count());
}
Xrm.Tooling库为连接通道和身份验证处理其他所有内容.除非您指定每次创建新通道(通过向连接字符串添加'RequireNewInstance = true'或在调用时设置useUniqueInstance
to ),否则库将重用现有的经过身份验证的通道.true
new CrmServiceClient
我使用以下代码进行快速验证测试:
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...");
}
当我运行它时,RequireNewInstance=true
我得到以下控制台输出:
是时候得到客户#1:2216
时间到了WhoAmI#1:2394
是时候得到客户#2:4603
时间到了WhoAmI#2:4780
显然,创建每个连接花费的时间大致相同.
现在,如果我将其更改为RequireNewInstance=false
(默认值),我会得到以下内容:
是时候得到客户#1:3761
时间到了WhoAmI#1:3960
是时候得到客户#2:3961
时间到了WhoAmI#2:4145
哇,这是一个很大的区别.到底是怎么回事?在第二次调用时,Xrm.Tooling库使用现有的服务通道和身份验证(缓存它.)
你可以更进一步,将你的new CrmServiceClient
调用包装using
在一起,你会得到相同的行为,因为处理return instanced不会破坏缓存.
所以这将返回类似于上面的时间:
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}");
}
为了简化代码,我通常会创建一个静态类(也可以使用单例,但通常会过度使用)来返回一个CrmServiceClient
对象.这样我的代码就不会乱码,new CrmServiceClient
如果我想改变连接的方式.
要从根本上回答这个问题using
,我们不需要使用它,因为没有什么可以发布.所有方法调用都将执行完成或抛出异常,因此即使GC需要一段时间没有开放连接,因此会占用资源和/或阻止其他活动.