Thursday, November 18, 2021

Restriction Rules Explained

Currently Salesforce allows you to create rules that restrict the visibility of records. For example, even if we have the OWD of an object to Public Read or beyond, we can still hide its records from certain users by adding a rule called "Restriction Rule".

Restriction Rules help us to restrict access to selected records from a group of users. It is made Generally Available (GA) since Winter '22 of Salesforce.  Remember that the restriction rule can only be created from the lightning experience and not from the classic experience.  We will take an example to illustrate each of its functionality, pros, and cons.

Scenario : I have a custom object named Engagement holding a checkbox field "Active".  The OWD for this object is "Public Read Only," but there are a specific set of Users belonging to profile "Sales Executive" who should be denied access to Engagement records where Active is TRUE.  Due to the OWD being "Public Read Only," the user cannot be restricted from accessing it.  

Solution : A Restriction Rule becomes relevant at this point. So let's create one to address the problem.   Restriction Rules are object-specific and so which we need to navigate to the object to create one.

Navigation : Goto Setup > Object Manager > Choose the object for which the Restriction Rule has to be created and on the left pane an option "Restriction Rule" will be available.(Refer to the below image for Reference).  Then click on "New Rule" 



There will be 3 sections here:

1. 
Rule Detail :
This will hold the details of the rule.  Populate values for all the fields under the section "Rule Detail".  Ensure to check the checkbox "Is Active". 

2. 
User Criteria :This is the place where we have to specify the Users for which
 the restriction Rule should apply. 
Currently, only two options are available :
   i. User Criteria
       If we want to identify users by a field on the User object 
       (only on the User object, multi-levels are not supported)
   ii. Permission Criteria 
      If we want to identify Users by using a "Custom Permission"

For our scenario, we wish to apply rule to all users associated with profile "Sales Executive".  But we need to understand the fact that the field Profile on User is a lookup and so only ID of the profile will be available on the User record.  As Restriction Rules can access data on the User object but not on the associated object, we have copy ID of the profile and use it in our criteria.

3. Record Criteria

It is here where criteria of records to be shown are specified. Any record that doesn't meet the criteria will be not shown to the User.  Only those fields on objects (on which restrictions are written) will be able to be selected.
For our scenario we wish to apply the Restriction for the Engagements where Active is unchecked. (Refer to below image for reference)

Save the record and you are all set.  Despite OWD being "Public Read Only", Engagement records with Active checkbox checked will no longer be visible to Users belonging to profile "Sales Executive".

It's definitely a useful feature, but it's equally important to know what the limitations are. Below are some of them.

  • Restriction rules are not supported for all objects. Only custom objects, contracts, events, tasks, time sheets, and time sheet entries can be restricted.
  • You can only have one Filter Entry under "User Criteria" and "Record Criteria". You cannot configure any Filter Logic and have multiple Filter Entries.
  • Only "Equals" is available as "Operator" for sections "User Criteria" and "Record Criteria".
  • Checkbox, Text, Number, Date, DateTime, Time, and Id(Lookup) are the only data types supported.  Only fields belonging toe mentioned data-types will be coming up in the User/Record Criteria

It feels like there are many limitations and I hope limitations will be lessened and scope will be extended in the upcoming releases.

Source : https://developer.salesforce.com/docs/atlas.en-us.restriction_rules.meta/restriction_rules/restriction_rules_about.htm
  

Thanks for being such an awesome reader and I appreciate your feedback.

..Bazingaa..

Monday, November 1, 2021

Move Reports from one folder to another using Apex

In many cases, moving reports from one folder to another was a problem that we faced at least once and resorted to manual modifications as the approaches available to do this are very limited and have high limitations.  Same applies for deleting a report too.

It is possible to move reports from one folder to another by using some migration tools. However, we will not cover those approaches in this post, since using migration tool requires lot of manual intervention to perform retrieval and deployment.  

Before we start with our process, we need to have the below mentioned two classes created in your org 

Let's understand by taking an example.  In my org, there are two reports
  • Report "Numeric Methods" in Folder "Economics" and 
  • Report "Quant" in Folder "Commerce".  

Now let's try to move both of the reports into folder "Aptitude".   Point to remember here is we need to make use of the the Full API Name of the report (i.e., Folder Developer Name + '/'+ Report Developer Name) to make use of it in apex.

Folder Developer Name can be fetched with the below SOQL
SELECT Id, DeveloperName FROM Folder

Report DeveleloperName can be fetched with the below SOQL
SELECT Id, Name, DeveloperName FROM Report

For the above mentioned reports, this is how the full name looks like
  • Commerce/Quant
  • Economics/Numeric_Methods
Execute the below logic in anonymous block of Dev Console and this will move the two reports mentioned into folder "Aptitude".

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
//Below variable to hold the list of Reports to be moved
List<String> lstStrRepNames = new List<String>();
lstStrRepNames.add('Commerce/Quant');
lstStrRepNames.add('Economics/Numeric_Methods');

//Below variable to hold the Developer Name of target Folder
String strTargetFolder = 'Aptitude';

MetadataService.MetadataPort service = new MetadataService.MetadataPort();
service.SessionHeader = new MetadataService.SessionHeader_element();
service.SessionHeader.sessionId = UserInfo.getSessionId();

List<MetadataService.Report> reportsToUpdate = (List<MetadataService.Report>) service.readMetadata('Report', lstStrRepNames).getRecords();
for(MetadataService.Report objRep : reportsToUpdate){
    //In full name replace source folder with targetFolder by using '/' as seperator
    objRep.fullName = objRep.fullName.replace(objRep.fullName.substringBeforeLast('/'), strTargetFolder);
}
List<MetadataService.SaveResult> results = service.updateMetadata(reportsToUpdate);

Now coming to the process of deleting reports, let's try to delete the reports which we just moved to the folder "Aptitude".  The developer names are like below
  • Aptitude/Quant
  • Aptitude/Numeric_Methods
Execute the below logic in Anonymous Block and that will do the job of deleting them.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
//Below variable to hold the list of Reports to be deleted
List<String> lstStrRepNames = new List<String>();
lstStrRepNames.add('Aptitude/Quant');
lstStrRepNames.add('Aptitude/Numeric_Methods');

MetadataService.MetadataPort service = new MetadataService.MetadataPort();
service.SessionHeader = new MetadataService.SessionHeader_element();
service.SessionHeader.sessionId = UserInfo.getSessionId();

List<MetadataService.DeleteResult> results = service.deleteMetadata('Report', lstStrRepNames);


For demonstration purpose, I wrote the core-logic.  To keep it generic enough, you may have to write the logic written in an apex method with parameters and enhance it as per your requirement.

PS : Keep in your thoughts that, above logic cannot process more than 10 records in a single transaction.  So if the count is greater than 10, batch apex has to be leveraged to achieve the same

Hope this helps.  

..Bazingaa..

Thursday, September 9, 2021

Remove "Change Owner" Quick Action from List Views in Lightning

Hello There,
 

Have you tried removing the "Change Owner" quick action on List Views? tricky isn't it?

We also have an open Idea in our Salesforce IdeaExchange community: 

Currently with out-of-box settings, it is not allowed to remove/hide this quick action on list views and removing the change owner permission at profile level has its own consequences.


It is quite understood that in many business cases, we want to limit the ownership transfer. However, the above limitation comes as a loop hole.


Here is a workaround to get rid-off the "Change Owner" button on list-view using a Utility-Bar.  This process makes use of CSS to hide the Change Owner which gets loaded from an LWC present inside Utility Bar.  Let's understand the procedure of getting rid-off the "Change Owner".


Pre-Requisites :

  • Utility bar is required to be present to be present.

Steps :
  • Install the below managed package in your Salesforce org.
    • For Sandbox  - Link
    • For Production  - Link

  • After successful installation, copy the API Name of the object for which the "Change Owner" button needs to be removed on list-views and add it to the custom label "Object_Names_to_hide_Change_Onwer". 

[For multiple objects, add them into the custom label by separating them with a comma (',') operator.  If this has to be implemented for All the tabs, mention as ALL in the custom label].
  • Goto Setup > App Manager and edit the app in which the tab is present.  
    • Now click on "Utility Items" on the left side pane.
    • Click on "Add Utility Item", search for "hideOwner" and add it.
    • You can leave the label as-is or can modify it as per your need.  If you do not want to have any label, just leave with a dot "." as this is required value.
    • Remember to check the checkbox "Start Automatically" at the bottom and click on "Save"

  • Repeat the above step for different apps where the Object tab is present.  
  • Now navigate to the tab and the "Change Owner" quick action is gone! 



You can contact me via LinkedIN for any issues while using / installing package.  Thanks for being an awesome reader and feedback is much appreciated.  

..BazingaaaA..

Friday, September 3, 2021

Things to avoid in APEX (Part-2)

Incase you haven't seen the Part-1 of Things to Avoid in Apex, below is the link

https://adityanthiruchuri.blogspot.com/2021/08/things-to-avoid-in-apex.html


Let us understand few more tips / tricks in this post.

1. Use '==' over 'equals' whenever required

We all know that APEX is not case-sensitive.  But we need to understand that there are few methods in apex, which takes the case-type (lower/upper) into consideration.   When you use the method 'equals' it will return TRUE only if the LHS and RHS are of same value and same case-type. Look at the below example



If you still want to make use of "equals" without taking case-types into consideration you have to either use method "equalsIgnoreCase()" (or) convert both the LHS and RHS into either lower / upper case and then do the comparison, but remember that these methods wont work for "null" values.   Whereas, operator '==' does the job without any such case conversions.  Use method 'equals' to do a comparison only when you want the case-match to be taken into consideration.

2. Concatenation of Strings

If given a requirement to concatenate two strings, we all tend to use the operator '+', but what if I tell you that the method .join() consumes way lesser time than the operator '+'.. Let me elaborate by taking an example.  I am trying to prepare a String by adding all the names of Opportunities separated by a comma.  There are 8500 records present while executing the below logic.


Above code consumed CPU Time of 1049ms.  Now let me execute the same logic by getting rid off the '+' operator by using "join" instead.


Above code consumed CPU Time of just 586ms which is almost 50% lesser than the time taken by the "+" operator.  Also as you are creating a new collection variable, ensure to take the heap size to take into consideration.  You can do the above implementation in your own orgs to get the results.

3. Avoid un-necessary creation of collection variables while preparing Map

Let us take a scenario of preparing Map<Id, list<Opportunity>> where key is AccountId and value will be its associated Opportunities.  Most of us will be writing code like below


In the above logic we have created an extra list at line#6, populated it with the current iterating record and then added it to the map, so that override will happen.  We need to understand that maps are mutable and that gives us the flexibility to modify an element of a map directly without having to add it again.  Consider the logic below


By using the above approach, we completely eliminated the need of creating an extra list and using the same to override the existing value.  

4. Do not use String datatype for holding Id's

I have seen many instances where developers use data-type String to hold value of type "Id". There are many drawbacks of using that approach.  We all know that Id's can be of length 15 or 18 based on the case-sensitivity.  Let us take a simple example to understand the consequence.  I am just hardcoding for our scenario, but keep in thoughts that this is never encouraged as a practice.


Reference : https://salesforce.stackexchange.com/questions/348609/why-this-map-return-null-value/348616

We need to have our code always dynamic in nature.  We can understand from the above example that if we store 15 digit Id in a string, it will fail when used against 18 digit Id and vice-versa.  But if we use the use "Id" data-type rather than string for the above, logic works just smooth.



Hope you find this interesting.  There are still many points to add and few more will be posted soon.   Let me know in the comment section if you have any such tips.  Feedback is much appreciated and thanks for being an awesome reader.  

..Bazingaa..

Friday, August 27, 2021

Things to avoid in APEX (Part-1)

We all strive to write APEX in the best way possible and in this post I will cover few unique guidelines that will help to make your code perform better.

1. Initialization of List

If the ask is to write a SOQL Query to fetch the accounts and store them in a list, 8 out 10 developers will write like below.


We all tend to initialize a list, so that it won't be null.  But that's actually causing more harm by consuming more resources.  We must know that SOQL Query will always return a List of subject which is instantiated.  So in our scenario we are actually doing a shallow copy of the records from the list that was returned from SOQL to the list we created.  So if you get 5,000 records as part of your SOQL, you are copying all the 5000 to your list which is not at all required.  We can avoid the explicit initialization to get rid of the shallow copy by having the logic like below.


PS : Remember that initialization cannot be ignored all the time, but only for few specific scenarios as mentioned above

2. Fetch fields without mentioning them in SOQL

If there is a requirement to fetch the Id and Name of an account, most of us will write the SOQL like below :


But what if I tell you that Id field is not required to be explicitly mentioned in the SOQL Query and will be queried automatically.  Along with the ID, RecordTypeId is one field which is also available for you. 


Also not just this, when there is a relation among objects and your SOQL is on the child object, no matter whichever field you query from the associated parent record, parent record Id will be automatically fetched.


So while writing your SOQL's, have in thoughts that there are few fields available even without querying. 

3. Get value of Formula Field without any DML / SOQL

There could be multiple instances where we do the DML first so that the formula field gets populated and then query for it to use in our logic.  To elaborate my point, let me take an example.  Consider a scenario where there is an object by name "Measurement" and is having 3 fields Length (Number), breadth (Number) and Area (Formula). The area is a formula field which holds the value of length multiplied with breadth. So, in-order to get the value of area, we need to first insert a record and then write a SOQL like below. 


But we can completely avoid writing SOQL and DML for getting the value of the formula field by leveraging a pre-defined method called "recalculateFormuals".  In the below example I have no SOQL/DML but able to get the value of formula field for an un-inserted record on the fly. 



The above approach will be very helpful while writing test classes.

Reference : https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_class_System_Formula.htm

Replace .size() with .isEmpty() wherever applicable

Prior to performing any DML or SOQL where a collection variable is being used, we follow the practice of checking the size of collection to avoid un-necessary SOQL / DML.  


But we need to understand whenever. Size () is used, the processor should traverse through each and every item of the collection for getting the count, but whereas isEmpty() will just check for the very first record in the collection and if found, it returns true, else false. 

So now the time that is consumed by the method. Size () for a collection size of 10000 will be very higher (as it has to traverse through every item present) than the time consumed by the method. IsEmpty() (As the check is made only the very first record).  So whenever you are using. Size () > 0, replace it will. IsEmpty () to avoid time


 Hope you find this interesting.  There are still many points to add and I am planning to post part-2 of this soon.  Let me know in the comment section if you have any such tips.  Feedback is much appreciated and thanks for being an awesome reader.  


..Bazinga..

Wednesday, August 18, 2021

What is "Cache Control" in Static Resource ?

We all might have used "Static Resource" for loading Styles (CSS) / scripts (JS) / images and used them in our Visualforce, LWC etc.,  But while creating a static resource, there is an option called "Cache Control".  Ever wondered, what is it for ? This post will help us to understand the significance of "Cache Control"

 






Basically this field does hold two values

    1. Private
    2. Public

Are you under an impression that choosing private will make the resource to be not stored in cache, and choosing "public" will store the resource in cache ?  If yes, then you are wrong.  We need to understand the fact that no mater which option is chosen, the resource will be cached.  Let us understand the significance of those two values

Private : The resource will be cached in the SF server and is confined only to the Current User, which means though the resource is in cache, other User's cannot access the cached resource.  Faster load time can only be observed for the current user as cache is confined only to the Current User's session

Public : The resource will be cached in the SF server and the cache can be used by all the Users across the organization, which means the faster load time can be observed by all the Users.

Source : Static Resource in VF Page

Thanks for being an awesome reader and hope you find this interesting.


 ..Bazingaa..




Thursday, August 12, 2021

Analysis on CPU Timeout Exception

We all might have seen at-least once the exception 'Apex CPU time limit exceeded'.  If transactions consume too much CPU time, they will be shut down and for any synchronous transaction, Salesforce limits the amount of CPU time to 10 seconds.  Have to admit that It is very hard to find the root-cause for this as there could be multiple components that gets executed in a transaction and any component could be the reason for it. 

In this post, let us understand the procedure to figure-out the way of finding the time consumed by each component in a transaction.  I am writing a simple WFR on Account object to showcase the demonstration.

Below is the WFR written


Below is the Field Update associated


To identify the time consumed, let's make sure that the debug logs are enabled for the User.   Lets insert a contact record for an existing account and capture the time.  For capturing the time, let me walk you through the process.  
  1. Perform the action.  i.e., "Inserting contact" in this scenario
  2. Open Developer Console.  Click on "Logs" tab at the bottom left and open the corresponding debug log pertaining to the action made.
  3. Now click on Debug > Switch Perspective > Analysis (Predefined).  Refer to the below image for better understanding.

  4. Now different panels will appear and under "Slack Tree" section click on "Performance Tree".  Refer to the below image.   All the component types that get executed in the transaction will be shown here with the time and heap consumed.  

  5. As I do not have any other event-centric component, only WFR is coming up.
  6. As you can see, it will show the time taken / heap consumed by each component if present.  
This will help you to identify the component that consumed more time and then you can make change accordingly to fix the issue

..Bazingaa..

Tuesday, August 10, 2021

Enhanced Loop(For Each) Vs Traditional Loop(For)

If you have written a trigger, you must be familiar with the enhanced for-loop.  We all must have used the enhanced for-loops in our apex code at-least once.  But are they really efficient against the traditional For-loops ? In this blog, let us dig deep into the efficiency measures of the for-loops.

Let us consider an example of iterating through list of Opportunity records and manipulating a field-value for our experiment.  Look at the below snippet where we are trying to iterate a collection in traditional and enhanced way.


From the above snippet it is so clear that enhanced for-loop is so efficient over traditional for-loop because of the reasons :

  1. Un-necessary variables are not required to be created in enhanced for-loop
  2. We don't need to calculate the size of the collection for iteration
  3. Index is not required to access an element inside collection
These reasons are enough to conclude that enhanced for-loop has won the war against traditional for-loop.   But let me tell you that traditional for-loop is efficient than enhanced for-loop in few scenarios and one such is in CPU Time Consumption.  Yes, traditional for-loop consumes lesser time than enhanced for-loop and CPU Time out exception is a nightmare for most of the developers.    Can't believe me, let me use the above example to prove my point.  Before I proceed, let me make you aware of the below system method : 

Limits.getCPUTime() Returns the CPU time (in milliseconds) that has been used in the current transaction

I'll be using the above system method to calculate the time that a block of code consumes. 

I will be running both the loops running against a collection size of 5000.  Let me first start with enhanced for-loop to see the time consumption.  
List<Opportunity> lstOpp = [SELECT Id, Name, StageName FROM Opportunity LIMIT 5000];

Integer strtTime = Limits.getCPUTime(); //Fetch the time consumed so far
//Iterate through all the opportunities
//In an enhanced for-loop by iterating through collection oppList
for(Opportunity opp : oppList){
   opp.stageName = strStgName;
}
Integer endTime = Limits.getCPUTime(); //Get the time consumed so far
//Print the time consumed by the for-loop
system.debug('Time consumed by for-loop is '+(endTime-strtTime) +'ms');

Above code resulted with the below output 
16:49:58:065 USER_DEBUG [8]|DEBUG|Time consumed by for-loop is 178 ms

Now, let us run the same code by using traditional for-loop :
List<Opportunity> lstOpp = [SELECT Id, Name, StageName FROM Opportunity LIMIT 5000];

Integer strtTime = Limits.getCPUTime(); //Fetch the time consumed so far
//Iterate through all the opportunities
//In an enhanced for-loop by iterating through collection oppList
for(Integer i=0; i<lstOpp.size(); i++){
   lstOpp[i].stageName = strStgName;
}
Integer endTime = Limits.getCPUTime(); //Get the time consumed so far
//Print the time consumed by the for-loop
system.debug('Time consumed by for-loop is '+(endTime-strtTime) +'ms');
Above code resulted with the below output 
16:52:30:323 USER_DEBUG [11]|DEBUG|Time consumed by for-loop is 107ms

It is now clear that traditional for-loop took less time than the enhanced for-loop.  Now let us make few tweaks to the traditional for-loop.  Rather than having lstOpp.size(); at the condition level, let's create a new variable for holding the same, so that calculation of collection size can be avoided at each iteration.  As .size() is present at the condition place and condition check happens for each iteration .size() calculation happens for each iteration.
List<Opportunity> lstOpp = [SELECT Id, Name, StageName FROM Opportunity LIMIT 5000];

Integer strtTime = Limits.getCPUTime(); //Fetch the time consumed so far
//Iterate through all the opportunities
//In an enhanced for-loop by iterating through collection oppList
//Created a new variable "j" to hold the size(size will be calculated only once)
for(Integer i=0, j=lstOpp.size(); i<j; i++){
   lstOpp[i].stageName = strStgName;
}
Integer endTime = Limits.getCPUTime(); //Get the time consumed so far
//Print the time consumed by the for-loop
system.debug('Time consumed by for-loop is '+(endTime-strtTime) +'ms');

Change made : Created a new variable "j" to hold the size and the size will be calculated only once unlike the prior implementation, where the size calculation happens for each iteration.

16:52:30:323 USER_DEBUG [11]|DEBUG|Time consumed by for-loop is 97ms

PS : You may not get the same exact output when you execute the above snippet in your ORG, values will always be approximately derived.

From the above execution, we understood that traditional for-loop took just half the amount of time Enhanced for-loop consumes.  This reason is enough to conclude that traditional for-loop is efficient over Enhanced For-Loop.  If you have to iterate child records which comes as part of inner SOQL Query, traditional for-loop will take just 1/3rd time of enhanced for-loop.

Then why do we have Enhanced For-Loop ?
Everyone would have started their coding exercise only through traditional for-loop. If traditional for-loop is that great, then why do we have enhanced for-loop.  ? Do we have to replace all our enhanced for-loops with traditional for.  ? 

Answer is BIG "NO".  There are instances where enhanced for-loop is much efficient than the traditional one and one good example is HEAP size consumption.  Enhanced for-loop consumes very less heap size when compared with traditional for-loop.  I recommend you to use methods of "Limits" class to check the heap size, time consumption on your loops and then take a call on the kind of for-loop that better suits your purpose.  Hope you find this interesting. 

Thanks for being an awesome reader.   Feedback is much appreciated.

..Bazingaa..

Monday, August 9, 2021

Query for all the fields of an object in SOQL

We all might have come across scenarios where we want to query for all the fields of an object.  In SQL we use the symbol * to fetch all the fields, but unfortunately we do not have any such in SOQL.  SF recently came up with amazing new feature in Spring'21 where all the fields belonging to a single sObject can be queried.

We can now use the below keywords in our SOQL.

  • FIELDS(ALL) - Fetches all(including standard and custom) the fields of object.
  • FIELDS(STANDARD) - This fetches only the standard fields of the object.
  • FIELDS(Custom) - This fetches only the custom fields of the object.

For using the above Keywords, the pre-requisite is "LIMIT" keyword should be used with utmost value of "200".  This means that not more than 200 records can be fetched if any of the above mentioned keywords are present in the SOQL.  And also is not supported with an unbounded set of fields in this API

//Below query will fetch all the fields of the Account Object
SELECT FIELDS(ALL) FROM Account LIMIT 200

//Below query will fetch only the Standard fields of the Account Object
SELECT FIELDS(STANDARD) FROM Account LIMIT 200

//Below query will fetch only the custom fields of the Account Object
SELECT FIELDS(CUSTOM) FROM Account LIMIT 200
 PS: Above can be executed in "Query Editor" present inside Developer Console to check the results.  Only FIELDS(STANDARD) is made available to be used inside APEX.

Source : https://developer.salesforce.com/blogs/2021/01/new-soql-fields-function-is-ga

It is undoubtedly a wonderful feature but with the limitation of not fetching more than 200 records and not making it completely available in apex, it could not solve our purpose in all the scenarios.

To overcome this, let us make use of Dynamic SOQL to get all the fields of the record.  To make this generic enough, let's create a new static method which accepts object Name as String.   With the received objectName it will return a SOQL Query(String) that includes all the fields

public class Utils {
    public static String prepareSOQL(String sobjectName){
	String strSOQL = 'SELECT ';
	Map<String, Schema.SObjectField> fMap = Schema.getGlobalDescribe().get(sobjectName.toLowerCase()).getDescribe().Fields.getMap();
    
	for (Schema.SObjectField ft : fMap.values()){ 
		Schema.DescribeFieldResult fd = ft.getDescribe();
		if (fd.isUpdateable()){ // add field only if it is accessable
			strSOQL += fd.getName()+',';
		}
	}
	strSOQL = strSOQL.removeEnd(',');
	strSOQL += ' FROM '+sobjectName;
	return strSOQL;
    }
}

The above method accepts a string (objectName) and returns a SOQL Query of type string which includes all the fields and this can be invoked from any place when needed

//lstAcc will hold all the records with all the fields
String strSOQL = Utils.prepareSOQL('Account');
List<Account> lstAcc = Database.query(strSOQL);

If we use the approach of dynamic SOQL, we don't have to worry about the LIMIT clause, but remember to use this approach of querying for all the fields only when needed and also keep in thoughts that the SOQL Query length should not exceed more than 10K.


Tip : Usage of .keyset() is not supported in Dynamic SOQL.

Yes, you read it right.  We all tend to use Maps and have them part of our SOQL query.  But map.keyset() in a dynamic SOQL Query will not fetch the desired result.  You need to assign the map.keyset() to another set variable and use set in your SOQL.  It is because variables / collections can be used in dynamic SOQL, but not the methods.  


Hope you find it interesting.  Thank you for visiting and feedback is much appreciated!!! 


"....Bazingaa..."