2014-01-22 51 views
0

我有一種情況,我必須根據記錄是否有打開或關閉的項目將源記錄列表狀態列更新爲打開或關閉狀態 - 項目列表可以通過源項目的ID和項目中的客戶端ID將多個項目鏈接到源記錄,代碼是檢索客戶項目,然後檢查是否有結束日期,如果沒有 - 它的開放 - 如果有的話 - 它的封閉。這些sharepoint列表很大Sharepoint 2010 - 更新大列表,處理非常緩慢和超時

我已經寫了代碼,基本上允許我指定一個開始ID,然後它會在停止之前處理這麼多的記錄,當我點擊一個運行按鈕時 - 我把這個放到位,因爲這個過程非常緩慢甚至超時,但我不明白爲什麼它如此緩慢和不穩定 - 如果我嘗試處理超過150條記錄 - 超時,服務器本身是一個帶有24GB內存的八核系統,所以我不會不認爲它的服務器,它可能是我的代碼。

protected void Button1_Click(object sender, EventArgs e) 
    { 
     SPWeb web = SPControl.GetContextWeb(this.Context); 
     string SPsiteUrl = SPContext.Current.Web.Url; 
     Label1.Text = "Running"; 
     int start; 
     start = Convert.ToInt32(TextBox1.Text); 
     start = int.Parse(TextBox1.Text); 
     int end = start + 150; 
     int count = 0; 

     using (SPSite oSite = new SPSite(SPsiteUrl)) 
     { 
      using (SPWeb oWeb = oSite.OpenWeb("/Client")) 
      { 
       // get lists 
       SPList oList = oWeb.Lists["Source Records"]; 
       SPList pList = oWeb.Lists["Project"]; 

       // query Source Records 
       string sQuery = @"<Where><And><Geq><FieldRef Name='ID' /><Value Type='Number'>" + start + "</Value></Geq><Leq><FieldRef Name='ID'/><Value Type='Number'> "+ end +"</Value></Leq></And></Where>"; 
       string sViewFields = @"<FieldRef Name='ID' />"; 
       string sViewAttrs = @"Scope=""Recursive"""; 
       uint iRowLimit = 0; 

       var oQuery = new SPQuery(); 
       oQuery.Query = sQuery; 
       oQuery.ViewFields = sViewFields; 
       oQuery.ViewAttributes = sViewAttrs; 
       oQuery.RowLimit = iRowLimit; 

       SPListItemCollection collListItems = oList.GetItems(oQuery); 

       // for each item 

       foreach (SPListItem oListItem in collListItems) 
       { 
        // get the client id 

        int id = oListItem.ID; 

         count = count + 1; 
         //Label1.Text = "Checking record" + id; 
         bool isopen = false; 
         // for each client id access the projects list 
         // query the closed date 
         string Query = @"<Where><Eq><FieldRef Name=""Client_x003a_ID"" /><Value Type=""Text"">" + id + "</Value></Eq></Where>"; 
         string pViewFields = @"<FieldRef Name=""End_x0020_Date"" />"; 
         string pViewAttrs = @"Scope=""Recursive"""; 
         uint pRowLimit = 0; 
         var pQuery = new SPQuery(); 
         pQuery.Query = Query; 
         pQuery.ViewFields = pViewFields; 
         pQuery.ViewAttributes = pViewAttrs; 
         pQuery.RowLimit = pRowLimit; 
         SPListItemCollection ListItems = pList.GetItems(pQuery); 

         foreach (SPListItem ListItem in ListItems) 
         { 
          try 
          { 
           DateTime enddate = (DateTime)ListItem["End_x0020_Date"]; 
           if (enddate != null) 
           { 
            isopen = false; 
           } 
           // else if the date is null set the open to true 
           else 
           { 
            isopen = true; 
           } 
          } 
          catch 
          { 
           string enddate = null; 
           if (enddate == null) 
           { 
            // if the end date is present set project closed to true 
            isopen = true; 
           } 
          } 

         // if project is open 
         if (isopen) 
         { 
          oWeb.AllowUnsafeUpdates = true; 
          SPListItem itemupdate = oWeb.Lists["Source Records"].Items.GetItemById(id); 
          itemupdate["Status"] = "Open"; 
          itemupdate.Update(); 
          oWeb.AllowUnsafeUpdates = false; 
          // set records on source record to open 
         } 
         //else // project is closed 
         //{ 
         // oWeb.AllowUnsafeUpdates = true; 
         // SPListItem itemupdate = oWeb.Lists["Source Records"].Items.GetItemById(id); 
         // itemupdate["Status"] = "Closed"; 
         // itemupdate.Update(); 
         // oWeb.AllowUnsafeUpdates = false; 
         // // set the record to closed 
         //} 
        } 
       } 
       Label1.Text = "Finished Number of records checked: " + count + " of " + collListItems.Count; 
      } 
     } 
    }' 
+0

的代碼被編碼後的文件從WSP拉 - 已經編輯到包括整個代碼,包括註釋掉的代碼 – Carl

回答

-2

您需要更新嵌套循環的代碼。取而代之的是:

foreach (SPListItem item1 in sPList.GetItems(sPQuery1)) 

嘗試使用此:

SPListItemCollection items1 = sPList.GetItems(sPQuery1); 
foreach (SPListItem item1 in items1) 

請參閱本blog post瞭解詳情。

更新:你必須嘗試擺脫嵌套循環。我認爲你可以通過在源列表中添加項目列表中的參考來實現該目標,並參考End Date列。

+0

嗨, 謝謝對於這個,但沒有喜悅,我害怕.. – Carl

+1

你所建議的改變不會改變一件事情。 'foreach'循環只評估IEnumerable對象一次,而不是循環的每次迭代。這與您鏈接的博客帖子完全不同。 – Servy

1

代替

SPListItem itemupdate = oWeb.Lists["Source Records"].Items.GetItemById(id); 

試試這個:

SPListItem itemupdate = oWeb.Lists["Source Records"].GetItemById(id); 
+0

他的問題是他正在循環中執行復雜而昂貴的查詢,而這正是他的主要成本所在。這種改變根本不會有太大的改變。 – Servy

+1

對不起,但我強烈反對在這裏。 SPList.Items是一項非常昂貴的操作。基本上它會從列表中檢索所有項目。它發生在一個循環中。所以。如果「源記錄」列表中有1000-2000項,則需要花費大量時間考慮「foreach(SPListItem oListItem in collListItems)」。總的來說,這個代碼有幾個嚴重的問題,而不僅僅是一個。例如,SPWeb.Lists [「」]也是非常昂貴的操作,你應該從循環等移出 –

+0

但它只是有條件地發生。這是一個*問題,但它並沒有改變這個算法的核心設計是有缺陷的。他不應該通過雙重嵌套循環中的ID來獲取項目*,除此之外,他甚至不應該*擁有雙重嵌套循環,其中每個循環都表示一個數據庫查詢。所以雖然這確實解決了一些問題,但是當你完成之後,它仍然會留下一個破碎的解決方案 – Servy