4

我在联系人对象上有一个触发器,当我尝试在此触发器中更新用户记录时,我得到以下异常:

“MIXED_DML_OPERATION,在您更新非设置对象(反之亦然)后,不允许对设置对象进行 DML 操作:用户,原始对象:联系人”

触发代码:

trigger UpdateContactTrigger on Contact (after update) {

    User u = [SELECT Id, IsActive FROM User WHERE IsActive = true];

    u.IsActive = false;
    update u;

}

从联系人触发器更新用户记录的字段时,如何避免此错误?

4

2 回答 2

10

Salesforce 将对象分类为所谓的设置对象和非设置对象。User 是一个设置对象,而 Contact 是一个非设置对象。Salesforce 限制 DML 操作,因此不能在同一上下文中操作这两种对象。

此问题有一个解决方法,将冲突对象的 DML 代码放置到 @future 方法中,如本文档末尾和上一个答案中所述。

在我的情况下,使用@future 方法不起作用,因为用户上有一个更新触发器调用了另一个@future 方法,而Salesforce 不允许从另一个@future 方法调用@future 方法。

所以我想出了另一种解决方法,它适用于用户对象的某些情况。

从 API 版本 15.0 开始,Salesforce 实际上允许在与非设置对象更新相同的上下文中更新用户对象的自定义字段。因此,如果您需要更新用户的标准字段,您可以在用户对象上使用带有“更新前”触发器的自定义代理字段。

如果您需要更改用户的 IsActive 字段,请向用户添加自定义 IsActiveProxy 字段并在触发器中执行更新:

trigger UpdateContactTrigger on Contact (after update) {

    User u = [SELECT Id, IsActive FROM User WHERE IsActive = true];

    u.IsActiveProxy__c = false;
    update u;

}

然后在将代理字段值复制到标准字段的用户上创建一个“更新前”触发器:

trigger BeforeUpdateUserTrigger on User (before update) {

    for(User user : trigger.new) {

        if(user.IsActive != user.IsActiveProxy__c) {
            user.IsActive = user.IsActiveProxy__c;
        }

    }

}

就是这样!它对我有用。

于 2012-04-13T15:03:20.283 回答
2

您应该定义 @future 方法,该方法将执行更新并从触发器调用此方法。

@future
updateUser(){
    User u = [SELECT Id, IsActive FROM User WHERE IsActive = true];

    u.IsActive = false;
    update u;
}

并在触发器中调用它:

trigger UpdateContactTrigger on Contact (after update) {
    updateUser();
}    
于 2012-04-13T07:49:42.943 回答