目前,当我们从我们的网站查询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);
}
}
答案 0 :(得分:3)
根据您提供的内容,这看起来像是标准的延迟加载问题,但我猜测每个延迟加载都会导致Web服务调用。这将被称为“健谈”服务架构。您的目标应该是尽可能少的服务调用来检索单个请求的数据。
调用填写详细信息似乎是一个好主意,因为您可以重复使用各种服务方法,以便您只需要1或2级深度数据,或者一直向下,但是您需要付出陡峭的性能损失
最好定义一个Web服务调用,在这种情况下返回一个完整的对象图。我不知道您在CRM中是否使用了ORM层,但如果您进行特定调用以获取交付的完整图表,那么ORM可以将数据急切地提取到更少的SQL语句中。对Web服务的调用次数减少(以及随后对CRM数据存储的调用次数减少)会显着提高您的性能。
答案 1 :(得分:2)
就像其他答案中提到的那样,您的主要问题是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_join上运行foreach并将它放在一起。
***重要:不要使用基本Id属性(e.Id),坚持使用e.EntityNameId.Value(不知道为什么但是我需要一段时间来弄明白.Id返回默认Guid值“00000 ..”)。
答案 2 :(得分:1)
所以我可以理解为什么这可能需要一段时间。我想其他人都评论说你正在做很多网络服务电话。如果你得到片刻的话,知道个别电话是否很慢或仅仅是因为你制作了这么多电话会很有趣,我建议对此进行分析。
在任何情况下,我怀疑你不会使用强类型实体会获得更好的性能。
我建议使用FetchXml查询,这将允许您构建Sql Xml-Style查询。基本上你应该可以用一个电话替换你的许多我们的bservice电话。 MSDN有一个示例,还可以查看Stunnware FetchXml设计器,产品> Stunnware工具>下载和评估。它是为Crm 4而构建的,但几乎支持您需要的所有功能。
如果您不喜欢这样,您还可以尝试使用QueryExpression或OData,这两项都可以让您在一次点击中获取数据。
答案 3 :(得分:1)
在尝试了其他答案中的所有建议提示并进行进一步分析之后,在我们使用CRM的特定场景中,以及如何设置 - 我们决定绕过它。< / p>
我们最终使用了一些内置视图,这不是CRM文档中推荐的方法,但我们确实需要实现更高的性能,而这种情况下的CRM方法就是我们的方式。
对于其他阅读此内容的人,请参阅其他答案。
答案 4 :(得分:0)
因为查询不知道以后需要哪些字段,所以当只在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
};
查看此帖更多详情。