2012-09-11 20 views
4

當我們從我們的網站上查詢CRM時,我們的網站目前面臨着響應時間較慢(超過1分鐘)的問題。我們通過網絡服務使用CRM 2011。當我們調查時,我們發現時間花在了查詢CRM的時候。從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

我不知道這些特定的服務,但如果我是你可能與'foreach'語句開始。通常當查詢它們導致昂貴時。但是,我再次不知道你的服務細節。 –

回答

3

根據您提供的內容,這看起來像一個標準的延遲加載問題,除了我的猜測是每個延遲加載都會導致Web服務調用。這將被稱爲「健談」的服務架構。您的目標應該是儘可能少地調用服務來檢索單個請求的數據。

調用以填寫詳細信息似乎是一個好主意,因爲您可以針對只需要數據1或2級數據深度或全部數據的情況重新使用單個服務方法,但您付出的性能陡峭罰款。

你最好定義一個Web服務調用,在這樣的場景下返回一個完整的對象圖。我不知道您在CRM中是否使用了ORM層,但是如果您進行特定的調用以獲取完整的交付圖,那麼ORM可以將數據提前獲取到更少的SQL語句中。對Web服務的調用次數更少(隨後調用CRM數據存儲的次數更少)應能顯着提高您的性能。

+0

當我們遇到這個問題時,我們將其更改爲返回IQuerable 而不是T對象本身,這允許您的ORM外的代碼通過LINQ .Select()調用專門提及它需要哪些字段 – Seph

1

所以我可以看到爲什麼這可能需要一段時間。我認爲,正如其他人都評論說你正在進行一些Web服務調用。如果你有一點時間,知道個人電話很慢還是僅僅因爲你做得太多而感到有趣,我會建議分析一下。

無論如何我懷疑你不使用強類型實體會獲得更好的性能。

我會建議使用FetchXml查詢,這將允許您建立一個Sql的Xml風格的查詢。基本上,你應該能夠用一次呼叫代替你的許多我們的bservice呼叫。 MSDN就是一個例子,同時查看 FetchXml設計器,產品> Stunnware工具>下載和評估。它是爲Crm 4而打造的,但幾乎支持您需要的所有功能。

如果你不喜歡那樣,你也可以嘗試一個QueryExpressionOData,這兩者都應該允許你一次獲得你的數據。

1

嘗試所有建議的提示中的其他答案,並做進一步的分析,在我們特定的場景與我們使用的CRM,以及如何成立後 - 我們決定乾脆繞過它

我們最終使用了一些內置視圖,這不是CRM文檔中推薦的方法,但我們確實需要實現更高的性能,而在這種情況下,CRM方法正好符合我們的要求。

對於閱讀此內容的其他人,請參閱其他答案。

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(不知道爲什麼,但我花了一段時間才弄清楚。 Guid值「00000 ..」)。

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