C# 从CRM加载数据时出现性能问题
目前,当我们从我们的网站查询CRM时,我们的网站面临响应时间慢(超过1分钟)的问题。我们通过web服务使用CRM 2011。当我们调查时,我们发现时间花在查询CRM上 我们已经使用CrmSvcUtil.exe生成了映射到CRM实体的代理类。然后,我们创建一个上下文实例,并使用LINQ和C#查询CRM 查询时,我们使用LINQ将父对象加载到CRM,然后使用LoadProperty加载相关的子对象 我想知道是否有人使用不同的方法查询CRM,以及您在实施过程中是否遇到过类似的问题 我在下面提供了一个简化的示例查询C# 从CRM加载数据时出现性能问题,c#,performance,linq,web,crm,C#,Performance,Linq,Web,Crm,目前,当我们从我们的网站查询CRM时,我们的网站面临响应时间慢(超过1分钟)的问题。我们通过web服务使用CRM 2011。当我们调查时,我们发现时间花在查询CRM上 我们已经使用CrmSvcUtil.exe生成了映射到CRM实体的代理类。然后,我们创建一个上下文实例,并使用LINQ和C#查询CRM 查询时,我们使用LINQ将父对象加载到CRM,然后使用LoadProperty加载相关的子对象 我想知道是否有人使用不同的方法查询CRM,以及您在实施过程中是否遇到过类似的问题 我在下面提供了一个简
public void SelectEventById(Guid id)
{
var crmEventDelivery = this.ServiceContext.EventDeliverySet.FirstOrDefault(eventDelivery => eventDelivery.Id == id);
if (crmEventDelivery != null)
{
this.SelectCrmEventDeliveryWithRelationships(crmEventDelivery);
}
}
private void SelectCrmEventDeliveryWithRelationships(EventDelivery crmEventDelivery)
{
// Loading List of Venue Delivery on parent crmEventDelivery thats been passed
this.ServiceContext.LoadProperty(crmEventDelivery, Attributes.EventDelivery.eventdelivery_venuedelivery);
foreach (var venueDelivery in crmEventDelivery.eventdelivery_venuedelivery)
{
// Loading Venue on each Venue Delivery
ServiceContext.LoadProperty(venueDelivery, Attributes.VenueDelivery.venue_venuedelivery);
}
// Loading List of Session Delivery on parent crmEventDelivery thats been passed
this.ServiceContext.LoadProperty(crmEventDelivery, Attributes.EventDelivery.eventdelivery_sessiondelivery);
foreach (var sessionDelivery in crmEventDelivery.eventdelivery_sessiondelivery)
{
// Loading Presenters on each Session Delivery
ServiceContext.LoadProperty(sessionDelivery, Attributes.SessionDelivery.sessiondelivery_presenterbooking);
}
}
根据您提供的内容,这看起来像是一个标准的延迟加载问题,但我的猜测是每个延迟加载都会导致一个web服务调用。这将被称为“闲聊”服务体系结构。您的目标应该是尽可能少地进行服务调用以检索单个请求的数据 调用以填写详细信息似乎是一个好主意,因为您可以在只需要1级或2级数据的情况下重新使用单独的服务方法,或者在所有情况下都重新使用,但您需要付出高昂的性能代价
在这样的场景中,最好定义一个返回完整对象图的web服务调用。我不知道CRM中的ORM层是否/正在使用什么,但如果您进行特定调用以获取完整的交付图,则ORM可以将数据提取到更少的SQL语句中。减少对web服务的调用(随后减少对CRM数据存储的调用)将显著提高您的性能。因此,我可以看出这可能需要一段时间的原因。我认为,正如其他人评论的那样,您正在进行相当多的web服务调用。如果您有时间了解单个呼叫是否很慢,或者只是因为您拨打的电话太多,我建议您对此进行分析 在任何情况下,我都怀疑不使用强类型实体会获得更好的性能 我建议使用FetchXml查询,这将允许您构建Sql Xml样式的查询。基本上,您应该能够用一个呼叫来替换您的多个we-bservice呼叫。有一个例子,也可以查看FetchXml设计器,产品>Stunware工具>下载和评估。它是为Crm 4构建的,但实际上支持您需要的所有功能
如果你不喜欢,你也可以试试or,两者都可以让你一次就得到你的数据。在尝试了其他答案中的所有建议技巧并做了进一步的分析后,在我们使用CRM的特定场景中,以及它是如何设置的-我们决定简单地绕过它 我们最终使用了一些内置视图,这在CRM文档中不是推荐的方法,但我们确实需要实现更高的性能,而本例中的CRM方法正是我们的方式
阅读本文的其他人,也可以查看其他答案。与其他答案中提到的一样,您的主要问题是web服务调用的数量。没有人提到的是,您可以使用查询联接通过一次调用检索多个对象。因此,您可以尝试以下方法:
var query_join = (from e in ServiceContext.EventDeliverySet
join v in ServiceContext.VenueDeliverySet on e.EventDeliveryId equals v.EvendDeliveryId.Id
join vn in ServiceContext.VenueSet on v.VenueDeliveryId equals vn.VenueDeliveryId.Id
join s in ServiceContext.SessionDeliverSet on e.EventDeliveryId equals s.EvendDeliveryId.Id
where e.EventDeliveryId == id // *improtant (see below)
select new { EventDelivery = e, VenueDelivery = v, Venue = vn, SessionDeliver = s }).ToList();
然后,您可以在query\u join上运行foreach并将其放在一起
***重要事项:不要使用基本Id属性(e.Id),坚持使用e.EntityNameId.Value(不知道为什么,但我花了一段时间才弄明白。Id返回默认Guid值“00000..)。因为查询不知道以后需要哪些字段,当select子句中仅指定了实体时,将从该实体返回所有列。为了只指定要使用的字段,必须在select子句中返回一个新对象,指定要使用的字段 因此,与此相反:
var accounts = from acct in xrm.AccountSet
where acct.Name.StartsWith("Test")
select acct;
使用以下命令:
var accounts = from acct in xrm.AccountSet
where acct.Name.StartsWith("Test")
select new Account()
{
AccountId = acct.AccountId,
Name = acct.Name
};
查看此帖子了解更多详细信息
我不知道这些具体的服务,但如果我是,您可能会从这些
foreach
声明开始。通常在查询时,它们会导致昂贵的结果。但是,再一次,我不知道您的服务细节。当我们遇到这个问题时,我们将其更改为返回iqerable而不是t对象本身,这允许您的ORM外部代码通过LINQ.Select()调用专门提到它需要哪些字段