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
plapla 

how to get object fields info without using SOQL

Hello,

Given an object ID is there a way to get its fields info without using SOQL? See example below:

 

I have an aid = accountID given below

 

instead of writing

select id, parentId, name, Type from Account where Id =: aid

 

can I write something like below

 

string sname;

string stype;

 

sname = aid.name;

stype = aid.type;

 

basically it is similar to below statements and it works when I write a trigger like this one below.

Case CaseUpdated:trigger.new

GroupNo = CaseUpdated.Group__c;

 

Please advise

Paul

 

CheyneCheyne

You cannot do this in general. It works in the trigger, because the trigger automatically defines the trigger.new context variable, which is a list of sObjects (in this instance, cases) that were affected by the trigger.

GunishGunish
HI Paul,

Have you looked into using Dynamic Apex such as DescribeSObjectResult,

http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_Schema_DescribeSObjectResult_instance_methods.htm

Regards,
Gunish
Prashant TiwariPrashant Tiwari

Hi Paul,

 

Yoy can use the below code to achieve this:

 

Id objIds = 'aid;     // Salesforce ID


public set<string> sObjFieldName = new set<string>();  // list of feilds name


Schema.SObjectType token = objIds.getSObjectType();

Schema.DescribeSObjectResult dr = token.getDescribe();

sObjFieldName = dr.Fields.getMap().keyset();

 

sObjFieldName  contains all the feilds.

 

 

Hope this will help you !!

 

Please mark it as solved if it works as it may help others..!!

 

 

Thanks,

 

Prashant Tiwari

plapla

Thanks for the tips. However when I attempted to retrieve the field Type as below, I got the error message "Initial term of field expression must be a concrete Sobject: SET<String>". Please advise.

 

string stype;

Id objIds = CaseUpdated.AccountId;

set<string> sObjFieldName = newset<string>{'Id','Parentid','Type'}; // list of feilds name

Schema.SObjectType token = objIds.getSObjectType();

Schema.DescribeSObjectResult dr = token.getDescribe();

sObjFieldName = dr.Fields.getMap().keyset();

stype = sObjFieldName.Type;

 

k_bentsenk_bentsen

Cheyne is right, this won't work. The Schema class is used to get the metadata for objects such as their API name, their fields API names, etc, but cannot be utilized to access data from specific records.

 

Record field data is only available by records/variables that are currently in-context, which in triggers would be data from Trigger.new/old. You need SOQL to bring additional records/variables into context in order to access its data.

 

I know this information doesn't help solve your problem, but can you explain why you're looking to achieve this without SOQL? If you're worried about governor limits, like an SOQL query inside of a loop, there's generally always a way around it with the practice of building and iterating through lists/maps.

plapla

Yes I'm running into governor limit when embedding SOQL statements in a For loop. How do you go about avoiding this issue? There are multiple records to process in my case so how can you process these records without using For loop?

Please advise.

 

Thanks

Paul

 

CheyneCheyne

You can place all of the necessary records into a list using a single query, then iterate through that list using a for loop. Here's a basic example:

 

List<Case> cases = [SELECT "some fields" from Case WHERE "some criteria"];

for (Case c : cases) {
  //Do stuff with case here
}

update cases;

 It's hard to say exactly how you should structure your code without knowing exactly what it is you're trying to do, but this is the basic idea. I would also recommend reading the Apex Code Best Practices article. It talks about SOQL queries and for loops in the very beginning.

k_bentsenk_bentsen

I mean no disrespect when I say this, but not putting SOQL queries in loops is essentially rule #1 in Apex 101, so that leads me to believe that you have limited experience in writing triggers. I strongly recommned that you read through this best practice guide that Salesforce has put together for Apex: http://wiki.developerforce.com/page/Apex_Code_Best_Practices

 

With that being said, the (what I feel) cut and dry method to avoid putting an SOQL query inside a loop is as follows:

 

trigger NoSOQLInLoop on ObjectA (after insert, after update){
    
    List<Id> objbIDs = new List<Id>();
    
    for(ObjectA oa: Trigger.new){
        if(/*some logic/condition(s)*/){
            objbIDs.add(o.ObjectB__c); // assume ObjectB__c is the API name for the field that references ObjectB on ObjectA
        }
    }
    
    if(!objaIds.isEmpty()){ // if no records for Object A were found that meet the above criteria, trigger will exit at this point
        List<ObjectB> objBList = [SELECT Id, Name, /* other fields */ FROM ObjectB WHERE Id IN :objbIDs];
        for(ObjectB ob: objBList){
            /*make necessary changes to ObjectB*/
        }
        update objBList; // saves changes to the database
    }
}

 

Basically what this does is build a list of Ids so you can query to obtain all related records in a single SOQL query. Let me know if you need to clarify anything. Also, if you want to provide some more specific requirements for what you're trying to do, I'd be happy to try to help you get started.

plapla

Thanks for your tips. Below is the requirements from business users:

we have an account structure like below:

client (top)

  carrier

    account

      group (bottom)

 

Given an account at the group level for example, I have to traverse to next top level by its parentid, if parentId exist (which is account level), traverse to next top level which is carrier and finally to the client top level. Below is a portion of my code. Hope you got the idea from here. So how do you go about doing this without running into SOQL governor limit?

 

if (accName.Type == 'Group'){

 

if (accName.parentId != null){

List<Account> accName1 = [select id, parentId, name, Type fromAccountwhereId =: accName.parentId];

 

if (accName1[0].parentId != null){

List<Account> accName2 = [select id, parentId, name, Type fromAccountwhereId =: accName1[0].parentId];

 

if (accName2[0].parentId != null){

List<Account> accName3 = [select id, parentId, name, Type fromAccountwhereId =: accName2[0].parentId];

Clients = accName3[0].id;

}

else{

Clients =

null;

}

}

 

}

 

}

// Type = Group

 

 

 

k_bentsenk_bentsen

What needs to happen when you get to the top level client account?

plapla

When it gets to the client level, I will then populate this account name in the client field of the case object.

 

Thanks