function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
alaschgarialaschgari 

Dynamic/Generic SObject update method for Trigger

Hey folks,

I want to implement a method that is able to update a couple of objects which all have the same lookupfields:

 

Object1.LookupField1

Object1.LookupField2

Object2.LookupField1

Object2.LookupField2

 

My idea looks something like this:

 

trigger Object1Trigger on Object1 (before insert)
{
   for(Object1 o1 : trigger.new)
   {
      o1 = updateLookups(o1);
   }
}

trigger Object2Trigger on Object2 (before insert)
{
   for(Object1 o2 : trigger.new)
   {
      o2 = updateLookups(o2);
   }
}


updateLookups(SObject obj)
{
   /* Logic to determine userId1 & userId2 */
//TODO

obj.put(LookupField1, userId1);
obj.put(LookupField2, userId2); return obj; }

 Is this a good solution and if

YES: how do I have to implement it?

NO: which solution is even better?

 

Cheers

Josh :-)

 

Best Answer chosen by Admin (Salesforce Developers) 
sfdcfoxsfdcfox

That's what we did; many objects that have parallel fields, but possibly different names (because of managed packaging...). It's a very decent approach; it encourages code reuse, reduces overall code complexity, and makes it easier to isolate problems (and fix problems that affect all the various types at once). Our solution was to have a "field map" object. Here's a brief summary:

 

public class FieldMap {
  public sobjectfield quantity, salesprice, totalprice;
  static map<sobjecttype, fieldmap> fieldmaps;
  static {
    fieldmaps = new map<sobjecttype, fieldmap>();
  }
  private FieldMap(SObjectType ent) {
    if(ent == opportunitylineitem.sobjecttype) {
      quantity = opportunitylineitem.quantity;
      salesprice = opportunitylineitem.unitprice;
      totalprice = opportunitylineitem.total_price__c;
    }
    if(ent == orderlineitem__c.sobjecttype) {
      quantity = orderlineitem__c.quantity__c;
      salesprice = orderlineitem__c.salesprice__c;
      totalprice = orderlineitem__c.totalprice__c;
    }
  }
  public static FieldMap forEntity(SobjectType ent) {
    if(!fieldmaps.containskey(ent))
      fieldmaps.put(ent, new fieldmap(ent));
    return fieldmaps.get(ent);
  }
}

We use a "singleton" type setup so each entity will be initialized only once. This cuts down on our code being called multiple times (which will likely happen); there's actually close to 20 fields per entity, so this cuts down on the number of statements called.

 

So, when we get around to, for example, calculating the total price, we can do this:

 

// record is an existing opportunitylineitem entry.
fieldmap fm = fieldmap.forentity(opportunitylineitem.sobjecttype);
decimal quantity = (decimal)record.get(fm.quantity),
  salesprice = (decimal)record.get(fm.salesprice);
record.put(fm.totalprice,quantity*salesprice);

Obviously, we have a bit more error-checking, but it should outline the usage fairly well.

All Answers

sfdcfoxsfdcfox

That's what we did; many objects that have parallel fields, but possibly different names (because of managed packaging...). It's a very decent approach; it encourages code reuse, reduces overall code complexity, and makes it easier to isolate problems (and fix problems that affect all the various types at once). Our solution was to have a "field map" object. Here's a brief summary:

 

public class FieldMap {
  public sobjectfield quantity, salesprice, totalprice;
  static map<sobjecttype, fieldmap> fieldmaps;
  static {
    fieldmaps = new map<sobjecttype, fieldmap>();
  }
  private FieldMap(SObjectType ent) {
    if(ent == opportunitylineitem.sobjecttype) {
      quantity = opportunitylineitem.quantity;
      salesprice = opportunitylineitem.unitprice;
      totalprice = opportunitylineitem.total_price__c;
    }
    if(ent == orderlineitem__c.sobjecttype) {
      quantity = orderlineitem__c.quantity__c;
      salesprice = orderlineitem__c.salesprice__c;
      totalprice = orderlineitem__c.totalprice__c;
    }
  }
  public static FieldMap forEntity(SobjectType ent) {
    if(!fieldmaps.containskey(ent))
      fieldmaps.put(ent, new fieldmap(ent));
    return fieldmaps.get(ent);
  }
}

We use a "singleton" type setup so each entity will be initialized only once. This cuts down on our code being called multiple times (which will likely happen); there's actually close to 20 fields per entity, so this cuts down on the number of statements called.

 

So, when we get around to, for example, calculating the total price, we can do this:

 

// record is an existing opportunitylineitem entry.
fieldmap fm = fieldmap.forentity(opportunitylineitem.sobjecttype);
decimal quantity = (decimal)record.get(fm.quantity),
  salesprice = (decimal)record.get(fm.salesprice);
record.put(fm.totalprice,quantity*salesprice);

Obviously, we have a bit more error-checking, but it should outline the usage fairly well.

This was selected as the best answer
alaschgarialaschgari

Hi sfdcfox!

 

Thank you very much for your solution!

Yes, this can be one of the possible solutions.

 

Does anyone have a second solution?