2013-01-10 45 views
2

我對Apex相對來說比較新,但是我有一個關於我正在創建的批處理作業的問題。我正在嘗試根據我公司的領土調整插入AccountTeamMember記錄。該代碼似乎工作正常,但有一個缺陷:它只能爲每個用戶插入100個AccountTeamMember記錄(它應該更接近400,因爲這是我在dev dev沙箱中加載的數量)。有誰知道我可以做些什麼來爲每個用戶的所有帳戶插入AccountTeamMember記錄,而不是~400的100個?這是否與包括親子關係和州長限制在內的查詢有關,因爲它是一個偶數(100)?Apex批處理不執行所有記錄

下面是相關代碼:

//list to hold new account teams 
List<AccountTeamMember> acctMembers = new List<AccountTeamMember>(); 

//list to hold new account sharing rules 
List<AccountShare> acctSharingRules = new List<AccountShare>(); 

global Database.querylocator start(Database.BatchableContext BC){ 
String query = 'SELECT (SELECT User__c FROM Territory_Users__r), (SELECT Account__c FROM Territory_Accounts__r) FROM Territory_Master__c'; 
return Database.getQueryLocator(query);} 

global void execute(Database.BatchableContext BC, List<sObject> scope){ 

for (sObject s : scope) { 
    Territory_Master__c tm = (Territory_Master__c) s; 
    Territory_User__c[] userList = tm.getSObjects('Territory_Users__r'); 
    Territory_Account__c[] accountList = tm.getSObjects('Territory_Accounts__r'); 


    if (userList != null && accountList != null){ 
     for(Territory_User__c uu : userList){ 
      for(Territory_Account__c aa: accountList){ 
       AccountTeamMember addRecord = new AccountTeamMember(); 
       addRecord.AccountId = aa.Account__c; 
       addRecord.TeamMemberRole = 'Sales Rep'; 
       addRecord.UserId = uu.User__c; 
       acctMembers.add(addRecord); 

       AccountShare addSharing = new AccountShare(); 
       addSharing.AccountId = aa.Account__c; 
       addSharing.OpportunityAccessLevel = 'Read'; 
       addSharing.CaseAccessLevel = 'Read'; 
       addSharing.AccountAccessLevel = 'Edit'; 
       addSharing.UserOrGroupId = uu.User__c; 
       acctSharingRules.add(addSharing); 

      } 
     } 
    } 
} 

//DML 
if(acctMembers.size() > 0){ 
    insert acctMembers; 
} 
if(acctSharingRules.size() > 0){ 
    insert acctSharingRules; 
} 
} 

感謝,

三分球

FYI:這是一個基於問題的答案最終結果:

global Database.querylocator start(Database.BatchableContext BC){ 
String query = 'SELECT Id FROM Territory_Master__c'; 
return Database.getQueryLocator(query);} 

global void execute(Database.BatchableContext BC, List<sObject> scope){ 

for(sObject s : scope){ 
    Territory_Master__c tm = (Territory_Master__c) s; 

    List<Territory_User__c> userList = [SELECT User__c FROM Territory_User__c WHERE Territory_Master__c = :tm.Id]; 
    List<Territory_Account__c> accountList = [SELECT Account__c FROM Territory_Account__c WHERE Territory_Master__c = :tm.Id]; 

    if (userList != null && accountList != null){ 
     for(Territory_User__c uu : userList){ 
       for(Territory_Account__c aa: accountList){ 
       AccountTeamMember addRecord = new AccountTeamMember(); 
       addRecord.AccountId = aa.Account__c; 
       addRecord.TeamMemberRole = 'Sales Rep'; 
       addRecord.UserId = uu.User__c; 
       acctMembers.add(addRecord); 

       acctSharingRules.add(new AccountShare(
        AccountId = aa.Account__c, 
        OpportunityAccessLevel = 'Read', 
        CaseAccessLevel = 'Read', 
        AccountAccessLevel = 'Edit', 
        UserOrGroupId = uu.User__c) 
       ); 
      } 
     } 
    } 
} 

//DML 
if(acctMembers.size() > 0){ 
    insert acctMembers; 
} 
if(acctSharingRules.size() > 0){ 
    insert acctSharingRules; 
} 
} 

回答

1

我懷疑你的子查詢是有限的,這是你的工作,以確保你已經完成這個記錄,然後再轉到下一個。

http://www.salesforce.com/us/developer/docs/api/Content/sforce_api_calls_soql_relationships.htm

子查詢的結果是一樣的,經常查詢的結果,你可能需要 使用queryMore()來檢索所有的記錄,如果有很多 孩子。例如,如果你發出一個包含 子查詢,您的客戶端應用程序必須從 子查詢處理結果,以及對賬戶查詢

(例子是Java調用Salesforce的,所以不要複製粘貼代碼,試圖理解這個概念。據我知道的Apex沒有這個queryMore方法,它是集成只)

選項1

滑稽的是,它理論上應該工作,如果你」 d將for循環更改爲:

for(Territory_User__c uu : tm.getSObjects('Territory_Users__r')){ 
    for(Territory_Account__c aa: tm.getSObjects('Territory_Accounts__r')) 

這是因爲寫的方式should automatically call their internal queryMore()循環。

如果它不起作用(我還沒有測試過),你將不得不做更復雜的更改。

選項2

取下主查詢的子查詢,你必須把他們的execute()。事情是這樣的:

for(sObject s : scope){ 
    Territory_Master__c tm = (Territory_Master__c) s; 

    for(Territory_User__c uu : [SELECT User__c FROM Territory_User__c WHERE Territory_Master__c = :tm.Id]){ 
     for(Territory_Account__c aa: [SELECT Account__c FROM Territory_Account__c WHERE Territory_Master__c = :tm.Id]){ 
      acctMembers.add(new AccountTeamMember(
       AccountId = aa.Account__c, 
       TeamMemberRole = 'Sales Rep', 
       UserId = uu.User__c) 
      ); 

      acctSharingRules.add(new AccountShare(
       AccountId = aa.Account__c, 
       OpportunityAccessLevel = 'Read', 
       CaseAccessLevel = 'Read', 
       AccountAccessLevel = 'Edit', 
       UserOrGroupId = uu.User__c) 
      ); 
     } 
    } 
} 

旁註

  1. 有你會打的(跨所有對象檢索50K行區域主/用戶/客戶的限制的機會。如果?這種情況下,您可能必須限制批量作業的範圍(可選的第二個參數傳遞給Database.executeBatch())。
  2. 這個技巧可以讓您的腳本執行位速度更快,使用較少的語句(這樣你就不會觸及調控器限制):

    acctSharingRules.add(new AccountShare(
        AccountId = aa.Account__c, 
        OpportunityAccessLevel = 'Read', 
        CaseAccessLevel = 'Read', 
        AccountAccessLevel = 'Edit', 
        UserOrGroupId = uu.User__c) 
    ); 
    
+0

非常有幫助的答案。不幸的是,選項1的表現與我的原始代碼一樣,但是您使用選項2進行了固定。我稍微修改了代碼以適應邏輯,最終結果完美無瑕。我也考慮到你的附註。感謝您的幫助。 – Trey

+0

很高興幫助我自己也學到了一些東西:)其實我已經有了一個腦力激盪的時刻。忽略大約50K行讀取的位。你最擔心的應該是在每個上下文中插入10K行(所以每個'execute()'調用);) – eyescream

0

你的代碼在那裏沒有什麼明顯的錯誤,所以如果我是你,我會盡量縮小這個高度問題的原因。問題的根源將是一個:

  • 您的查詢只返回在爲accountList或用戶列表100個項目或兩者
  • 插入只能同時處理100個項目,並默默未能插入其餘
  • 插入之後100

失敗的項目如果您還沒有這樣做的話,你應該熟悉在Salesforce.com中使用調試日誌(安裝|監控|調試日誌)。打開它們,然後運行此代碼與一些System.debug調用在那裏弄清楚:

  • userList和accountList中有多少項?
  • 如果它超過100,當你去插入共享行時,是否有一些插入失敗?如果你使用Database.insert()而不是隻是插入語句,那麼你會得到一個SaveResult [],它會告訴你每一行你試圖插入的是否成功或錯誤。

所以我不能說我的頭頂爲什麼這是失敗的,我沒有看到任何特定的限制應該在這裏應用,但上面應該可以幫助您至少調試它。

+0

謝謝您的回答。我能夠用輕微的重新編碼獲得它。 – Trey