2

私はApexに比較的慣れていませんが、作成しているバッチジョブについて質問があります。会社のテリトリーアラインメントに基づいてAccountTeamMemberレコードを挿入しようとしています。コードは正常に機能しているようですが、1つの欠点があります。ユーザーごとに100個のAccountTeamMemberレコードしか挿入されていません(開発サンドボックスにロードした数であるため、400に近いはずです)。〜400の100ではなく、ユーザーごとにすべてのアカウントにAccountTeamMemberレコードを挿入するために私ができることを誰かが知っていますか?偶数(100)なので、親子関係や知事制限などのクエリと関係があるのでしょうか。

関連するコードは次のとおりです。

//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;
}
}

ありがとう、

トレイ

参考:これは、質問への回答に基づく最終結果です。

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;
}
}
4

2 に答える 2

1

サブクエリが制限されているのではないかと思います。次のレコードに進む前に、このレコードを終了したことを確認するのはあなたの仕事です。

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

サブクエリの結果は、子が多い場合にqueryMore()を使用してすべてのレコードを取得する必要があるという点で、通常のクエリの結果と似ています。たとえば、サブクエリを含むアカウントでクエリを発行する場合、クライアントアプリケーションはサブクエリの結果も処理する必要があります

(例はSalesforceを呼び出すJavaの場合なので、コードをコピーして貼り付けないで、概念を理解してみてください。ApexにこのqueryMoreメソッドがないことを知っている限り、統合専用です)

オプション1

おかしなことに、forループを次のように変更すると、理論的には機能するはずです。

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

これは、そのように記述されたforループは、内部の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行の制限に達する可能性はありますか?その場合、バッチジョブの範囲を制限する必要があります(オプションの2番目のパラメーターがに渡されますDatabase.executeBatch())。
  2. このトリックにより、スクリプトの実行が少し速くなり、使用するステートメントが少なくなります(したがって、別のガバナーの制限に達することはありません)。

    acctSharingRules.add(new AccountShare(
        AccountId = aa.Account__c,
        OpportunityAccessLevel = 'Read',
        CaseAccessLevel = 'Read',
        AccountAccessLevel = 'Edit',
        UserOrGroupId = uu.User__c)
    );
    
于 2013-01-10T20:10:42.627 に答える
0

そこにあるコードには明らかに問題はないので、もし私があなたなら、問題の原因を絞り込もうとします。問題の原因は次のいずれかになります。

  • クエリは、accountListまたはuserList、あるいはその両方で100個のアイテムのみを返します
  • インサートは一度に100個のアイテムしか処理できず、残りのアイテムを黙って挿入できません。
  • 100以降のアイテムの挿入が失敗している

まだ行っていない場合は、Salesforce.comのデバッグログの使用に慣れておく必要があります([設定]、[監視]、[デバッグログ])。それらをオンにしてから、いくつかのSystem.debug呼び出しを使用してこのコードを実行し、次のことを理解します。

  • userListとaccountListにはいくつのアイテムがありますか?
  • 100を超える場合、共有行を挿入しようとすると、それらの挿入の一部が失敗しますか?挿入ステートメントだけでなくDatabase.insert()を使用すると、SaveResult []が返され、挿入を試みた行ごとに、成功したかエラーになったのかがわかります。

したがって、なぜこれが失敗するのかを頭の中で言うことはできません。ここで適用する必要のある特定の制限はわかりませんが、上記は少なくともデバッグに役立つはずです。

于 2013-01-10T20:06:03.390 に答える