Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/298.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 从CRM加载数据时出现性能问题_C#_Performance_Linq_Web_Crm - Fatal编程技术网

C# 从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,以及您在实施过程中是否遇到过类似的问题 我在下面提供了一个简

目前,当我们从我们的网站查询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()调用专门提到它需要哪些字段