1

几天前一切正常,除了配置文件外,没有对系统进行任何新的更改。

突然我收到这个错误信息:

错误:无效数据。查看以下所有错误消息以更正您的数据。
Apex 触发器 generateUniqueBidId 导致意外异常,请联系您的管理员: generateUniqueBidId: System.LimitException: Too many SOQL queries: 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. You might hit a limit of no more than 10K rows inserted/updated in single transaction (you should at least add LIMIT clause).
  2. You're mixing work on data that's in the context of the trigger with data fixes on some unrelated stuff. You shouldn't "piggyback" because users won't understand why they see an error coming from data they didn't touch.
  3. Not to mention the fact that "last modified by" is now worthless in your system.

If it's one time activity to clean up your bad data (fix unique labels) - consider running a data fix and removing this code. If it's really a recurring situation - write a batch job.

Or investigate if you can write a workflow rule to generate the unique keys, looks like it's be doable and config beats coding a solution.

于 2013-02-12T09:37:23.403 回答