trigger validateCategoryOnBankAccount on Bank_Account__c(before insert, before Update) {

    Set <Id> doctorIds = new Set <Id> ();
    set <string> picval = new set <string> ();
    if (trigger.isInsert) {
        for (Bank_Account__c bank: trigger.new) {
            if (bank.Category__c != null && bank.Doctor__c != null) {
                doctorIds.add(bank.Doctor__c);
                picval.add(bank.Category__c);
            }
        }
    }

    if (trigger.IsUpdate) {
        for (Bank_Account__c bank: trigger.new) {
            if (bank.Category__c != null && bank.Doctor__c != null) {
                if (bank.Category__c != trigger.oldmap.get(bank.id).Category__c) {
                    doctorIds.add(bank.Doctor__c);
                    picval.add(bank.Category__c);

                }
            }
        }
    }
    if (doctorIds != null && doctorIds.size() > 0) {
        list < Bank_Account__c > banklist = [select Id, Name, Doctor__c, Category__c from Bank_Account__c where Doctor__c in: doctorIds AND Category__c =: picval];
        if (banklist.size() > 0) {
            for (Bank_Account__c bank: trigger.new) {
                bank.addError('Bank Account with this category exists!');
            }
        }
    }

}
share|improve this question

Yes and no

No need for seperate block for update and insert they are doing almost (thanks DerekF for pointing out the additional if) the same thing and they can be consolidated pretty efficiently.

Also

if (doctorIds != null && doctorIds.size() > 0) {
    list < Bank_Account__c > banklist = [select Id, Name, Doctor__c, Category__c from Bank_Account__c where Doctor__c in: doctorIds AND Category__c =: picval];
    if (banklist.size() > 0) {
        for (Bank_Account__c bank: trigger.new) {
            bank.addError('Bank Account with this category exists!');
        }
    }
}

This is not bulkified. According to this logic, if even one record causes this code to be entered then ALL records will have the error added to them without regard to the specific record that you are actually trying to throw the error for

Without much thought about it this may achieve what you want for the last part

if (doctorIds != null && doctorIds.size() > 0) {
        list < Bank_Account__c > banklist = [select Id, Name, Doctor__c, Category__c from Bank_Account__c where Doctor__c in: doctorIds OR Category__c =: picval];
        doctorIds.clear(); //Clear previously stored values
        picval.clear();
        for(Bank_Account__c tmp : bankList){ //populate with existing values
            doctorIds.add(tmp.Doctor__c); 
            picval.add(tmp.Category__c);
        }
            for (Bank_Account__c bank: trigger.new) { //Iterate through tigger records
                if(doctorIds.contains(bank.Doctor__c) || picval.contains(bank.Category__c) //If the collections contain the values in the record throw error
                    bank.addError('Bank Account with this category exists!');
            }
        }
    }

There are certainly better ways do do this and rewrite the whole trigger though, I just do not have the bandwidth to put into it at the moment.

share|improve this answer
    
OP does have an additional if in the update block that doesn't appear in the insert block, but it can still be consolidated into a single loop. I'd also argue that the entire trigger is properly bulkified, it just simply contains a (fairly large, admittedly) semantic error. – Derek F May 11 at 16:07
    
@DerekF - I understand your point but the last part is technically not bulkified if it causes all records to error when one meets the criteria. Semantics I guess.....Thanks for pointing out the additional if. I updated that part of the answer. – Eric May 11 at 16:10
    
So,how can i bulkfied this trigger? – Jatin Puri May 11 at 16:51
    
There's a lot of minor optimizations you can do here, too. No need to check if doctorIds is null, and no need to see if bankList is empty before you loop over it. – sfdcfox May 11 at 16:51
    
@JatinPuri - Thats a different question, please feel free to ask a new one with that question. Did you read my answer? I provided some pointers.... – Eric May 11 at 16:53

There's a lot better way to code your intent than you've done here. Here's an alternative (untested):

trigger validateCategoryOnBankAccount on Bank_Account__c(after insert, after update, after undelete) {
  Set<String> doctorIds = new Set<String>(), pickVals = new Set<String>();
  Map<Bank_Account__c, Id> banks = new Map<Bank_Account__c, Id>();
  for(Bank_Account__c record: Trigger.new) {
    Bank_Account__c key = new Bank_Account__c(record.Doctor__c, record.Category__c));
    if(banks.Doctor__c != null && banks.Category__c != null) {
      if(banks.containsKey(key)) {
        record.addError('Bank Account with this category exists!');
      } else {
        banks.put(key, record.Id);
        doctorIds.add(record.Doctor__c);
        pickVals.add(record.Category__c);
      }
    }
  }
  for(Bank_Account__c oldRecord: [SELECT Doctor__c, Category__c FROM Bank_Account__c WHERE Doctor__c = :doctorIds AND Category__c = :pickVals]) {
    Bank_Account__c key = new Bank_Account__c(Doctor__c=oldRecord.Doctor__c, Category__c=oldRecord.Category__c);
    Id recordId = banks.get(key);
    if(recordId != null && recordId != record.Id) {
      Trigger.newMap.get(recordId).addError('Bank Account with this category already exists!');
    }
  }
}

This also prevents duplicate bank accounts that may occur when a bank account is deleted, another is created, and then the first is subsequently undeleted.

All of the extra work checking if doctor/category has already changed is eliminated for the cost of a single extra query. In practice, this shouldn't have much of an effect on performance.

share|improve this answer
    
Wonder if the OP meant to have the combination of the doctor and category as a key or either or.....hmmmmm. It would seem that the combination is the desire based on the query but not sure if the was a logic error or purposeful... – Eric May 11 at 18:23

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.