1

数日前はすべて正常に機能し、プロファイル以外のシステムに新しい変更は加えられていません。

突然、次のエラーメッセージが表示されました。

エラー:データが無効です。以下のすべてのエラーメッセージを確認して、データを修正してください。
ApexトリガーgenerateUniqueBidIdにより予期しない例外が発生しました。管理者に連絡してください:generateUniqueBidId:System.LimitException:SOQLクエリが多すぎます:101

 trigger generateUniqueBidId on Bids__c (before insert) {

    Map<String, String> profilePrefixMap = new Map<String, String>();
    profilePrefixMap.put('Sales User', 'rds');
    profilePrefixMap.put('Super User', 'rds');
    profilePrefixMap.put('Standard User','SU');
    profilePrefixMap.put('System Administrator','SysAdmin');

    String defaultPrefix = ' ';
    User user = [SELECT ProfileId FROM User Where Id = :Userinfo.getUserId() LIMIT 1];
    Profile profile = [SELECT Name FROM Profile Where Id = :user.ProfileId LIMIT 1];
    List<Bids__c> recentBids = [SELECT Id, CreatedById, Bid_unique_label__c From Bids__c WHERE Bid_unique_label__c = NULL];

    /**Logics for updating old Bids with correct Bid_id. May be refactored away when all bids are updated
       Could cause problems if trigger system becomes to complicated. 
    */
    for (Bids__c bid : recentBids){
        String recentProfileName = [SELECT Profile.Name FROM User Where Id = :bid.CreatedById LIMIT 1].Profile.Name;
        String bidId = profilePrefixMap.get(recentProfileName);
        bid.Bid_unique_label__c =  ((bidId == null) ? defaultPrefix : bidId);           
    }
    upsert recentBids;

    for (Bids__c bid : trigger.new){
        String bidId = profilePrefixMap.get(String.valueOf(profile.Name));
        bid.Bid_unique_label__c = ((bidId == null) ? defaultPrefix : bidId);
    }

}
4

1 に答える 1

3

ループ内に SOQL があります。

for (Bids__c bid : recentBids){
    String recentProfileName = [SELECT Profile.Name FROM User Where Id = :bid.CreatedById LIMIT 1].Profile.Name;
    String bidId = profilePrefixMap.get(recentProfileName);
    bid.Bid_unique_label__c =  ((bidId == null) ? defaultPrefix : bidId);           
}
upsert recentBids;

これはパフォーマンス キラーであり、実際には、制限が 100 クエリであることに驚いています。以前は、トリガー コンテキストで 20 クエリを超えていませんでした。問題の簡単な解決策は、「ドット表記」で関係クエリを使用することです。これにより、クエリをループで作成する必要がなくなります。

List<Bids__c> recentBids = [SELECT Id, CreatedBy.Profile.Name, Bid_unique_label__c 
FROM Bids__c 
WHERE Bid_unique_label__c = NULL];

for (Bids__c bid : recentBids){
    String recentProfileName = bid.CreatedBy.Profile.Name;
    String bidId = profilePrefixMap.get(recentProfileName);
    bid.Bid_unique_label__c =  ((bidId == null) ? defaultPrefix : bidId);           
}
upsert recentBids;

このコードにはまだいくつかの問題があります。

  1. 1 回のトランザクションで挿入/更新される行数が 10,000 行以下という制限に達する可能性があります (少なくとも LIMIT 句を追加する必要があります)。
  2. トリガーのコンテキスト内にあるデータの作業と、無関係なもののデータ修正を混在させています。ユーザーは、触れていないデータに起因するエラーが表示される理由を理解できないため、「ピギーバック」するべきではありません。
  3. 言うまでもなく、「最終更新者」はシステムでは価値がありません。

不良データのクリーンアップ (固有のラベルの修正) が 1 回限りのアクティビティである場合は、データ修正を実行してこのコードを削除することを検討してください。それが本当に繰り返される状況である場合は、バッチ ジョブを記述します。

または、ワークフロー ルールを記述して一意のキーを生成できるかどうかを調査します。それは実行可能であり、構成はソリューションのコーディングよりも優れているようです。

于 2013-02-12T09:37:23.403 に答える