从CRM加载数据的性能问题

时间:2012-09-11 00:44:08

标签: 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);
            }
   }

5 个答案:

答案 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而构建的,但几乎支持您需要的所有功能。

如果您不喜欢这样,您还可以尝试使用QueryExpressionOData,这两项都可以让您在一次点击中获取数据。

答案 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
               };

查看此帖更多详情。

To Linq or not to Linq