Showing posts with label SOQL. Show all posts
Showing posts with label SOQL. Show all posts

Saturday, July 1, 2017

Field expression not allowed for generic SObject in Salesforce

Scenario:


Usually when we writing any trigger we will be following some best practices like One Trigger for One Object,Business logic in Handler Class ,Don't write the whole code in Trigger etc..This kind of error will receive when we are writing whole trigger logic in Separate Handler Class(Apex class) and we are referring to that trigger context variables  in that Apex class or  referring your sobjects in Trigger handler


Root Cause : 


Trigger Code

Trigger CaseTrigger on Case (Before Insert,Before Update,After insert) 
{
   if(Trigger.isBefore && (Trigger.isInsert || Trigger.isUpdate))
    {
        CaseTriggerHandler.duplicateCheck(Trigger.new);
    }
}

Handler Class

Public class CaseTriggerHandler
{ 
public static void duplicateCheck(List<Case> TriggerNew)
 {
         for (Case cs : TriggerNew) 
        {
           if(cs.status__c!=Trigger.OldMap.get(cs.Id).status__c)
            {
               System.debug('Status has changed');
            }
        }
 }
}

When your trying save above handler code you will end up with Field expression not allowed for generic SObject .


Solution:

The reason behind is that Trigger.OldMap is a generic variable that means it will be used for all objects so when your using this variable you need to tell the compiler what type of the SObject your referring from Trigger.OldMap. I have highlighted that code change in yellow color in below code.
        

Public class CaseTriggerHandler
{ 
public static void duplicateCheck(List<Case> TriggerNew)
 {
         for (Case cs : TriggerNew) 
        {
           if(cs.status__c!=((Map<Id,Case>)Trigger.OldMap).get(cs.Id).status__c)
            {
               System.debug('Status has changed');
            }
        }
 }
}


Thanks for visiting..hope this helps you!

System.ListException: Before Insert or Upsert list must not have two identically equal elements

We will receive this error when your adding same instance of record to list twice i.e.If your adding same record twice to the list you will end up with error.

Sample Code With Error

List<Case> listCase = new List<Case>();
Case cs = new Case();
cs.RecordTypeId = Schema.SObjectType.Case.getRecordTypeInfosByName().get('Bus').getRecordTypeId();
cs.Status ='Approved';
cs.Origin = 'Inbound Call';
listCase.add(cs);

Case cs1 = new Case();
cs1.RecordTypeId = Schema.SObjectType.Case.getRecordTypeInfosByName().get('Bus').getRecordTypeId();
cs1.Status ='Approved';
cs1.Origin = 'Inbound Call';
listCase.add(cs);  // I should add cs1 instance but I added cs which are already in list

insert listCase;

If you run the above code you will receive an error while inserting System.ListException: Before Insert or Upsert list must not have two identically equal elements ,that is because of adding same case record twice to the list ,you can see duplicate element in yellow color where actually it should be cs1 but added cs which is already there in list.

To avoid this error you can cross check your code whether your adding some where same instance of object twice to the list.

Error Free Code


List<Case> listCase = new List<Case>();
Case cs = new Case();
cs.RecordTypeId = Schema.SObjectType.Case.getRecordTypeInfosByName().get('Bus').getRecordTypeId();
cs.Status ='Approved';
cs.Origin = 'Inbound Call';
listCase.add(cs);

Case cs1 = new Case();
cs1.RecordTypeId = Schema.SObjectType.Case.getRecordTypeInfosByName().get('Bus').getRecordTypeId();
cs1.Status ='Approved';
cs1.Origin = 'Inbound Call';
listCase.add(cs1);   //Corrected here adding cs1 instance to list 

insert listCase;


Thanks for visiting..hope this helps you!

Tuesday, December 13, 2016

Sample GROUP BY Clause in SOQL

Sample SOQL query to fetch case count based on the owner.

SELECT Owner.name, COUNT(CaseNumber)
FROM Case
GROUP BY Owner.name




Thank you...Enjoy!

Tuesday, July 12, 2016

System.QueryException: List has no rows for assignment to SObject

Usually we will come across this type issue in many places and in many situations also .In the same way I have come across the same issue in one of the my class and I have done some work around it to fix this issue.I will explain this one with an example which may brings you an complete understanding about the issue.

Scenario:
I have 3 objects called Time_Track__c,Expert__c and User.Expert__c and User having a lookup relationship where User (Sforce_User__c) is acting as parent for Expert object and Time_Track__c and Expert__c also having lookup relationship where Time_Track__c is acting as child for Expert (Expert_Name__c) object .I have an visual force page which is using Time_Track__c  as a Standard Controller and I am having some extension class on same page .In the constructor of the extension class I am trying to query on Expert__c object based on logged in user to assign this expert to new time track as shown below

Source Code:
public class TrackExtn {
  public Time_Track__c timeTrack{get;set;} 

  public TrackExtn(ApexPages.StandardController controller) {
    timeTrack = new Time_Track__c();        
    timeTrack= (Time_Track__c)controller.getRecord();
       
    if(controller.getId()==null)
    {
       Expert__c exp = new Expert__c();
       //In below line you will receive List has no rows for assignment to SObject
       exp = [Select id from Expert__c where Sforce_User__c=:UserInfo.getUserId() limit 1];
       timeTrack.Expert_Name__c = exp!=null?exp.id:null;
           
    }

    }
}

Error:

When you execute the above code at run time if your having at least one matching Expert__c record for logged in user it will work very smoothly .If there is no matching Expert__c record for logged in user will end up with System.QueryException: List has no rows for assignment to SObject . Even if the matching record is not there it should continue fir the next lines with out throwing any error but here it's failing and terminating the complete execution. To handle this we need to follow below work around solution.


Workaround Solution:

We need to convert the Query result holder from SObject type to List<SObject> type that will resolve the issue .Please look at the below code for the work around solution

public class TrackExtn {
  public Time_Track__c timeTrack{get;set;} 

  public TrackExtn(ApexPages.StandardController controller) {
    timeTrack = new Time_Track__c();        
    timeTrack= (Time_Track__c)controller.getRecord();
      
    if(controller.getId()==null)
    {
        //Convert Sobject type to List<Sobject> type to store query result
        List<Expert__c> listexp =new List<Expert__c>();
        listexp = [Select id from Expert__c where Sforce_User__c =:UserInfo.getUserId() limit 1];
        System.debug('loggedinTech ..'+listexp );
        td.Technician__c = listexp.isEmpty()?null:listexp[0].id;
           
    }

    }
}

Thanks for visiting...Enjoy!

Monday, July 11, 2016

System.QueryException: Only variable references are allowed in dynamic SOQL/SOSL.

Error:

Whenever your working with Dynamic SOQL construction you should be very careful regarding the Single Quotes(',') or Open/Close parentheses'(' ')'  and bind variables(':') in query string.If your also getting the same error as mentioned above please refer below code.

Source Code:

public void fetchOrders()
{
List<Order__c> listOrders = new List<Order__c>();
String selWOStatus ='Test'  // Usually value for this comes from visual force page

String q ='SELECT Id, Name, Location__c,End_Date__c,Createddate FROM Order__c where 
           Location__r.OwnerId=:'+UserInfo.getUserId();
                        
if('All'.equalsIgnoreCase(selWOStatus))
  q + = ' AND (Createddate =LAST_N_MONTHS:6 OR End_Date__c < NEXT_N_MONTHS:6) LIMIT 1000'; 

else
  q + =' AND (Status =\''+String.escapeSingleQuotes(selWOStatus)+'\' 
         AND Createddate = LAST_N_MONTHS:6) LIMIT 1000';

System.debug('q....'+q); 

listOrders  = Database.query(q);

System.debug('listTSOOrders....'+listOrders);

}

When you run this above code at run time you will end up with System.QueryException: Only variable references are allowed in dynamic SOQL/SOSL .This is due to the (':') bind variable usage in dynamic query construction which will cause the error and that causes missing a single quote for logged in user ID as shown query string coming at run time as shown below

Actual Query String at Run time:

'SELECT Id, Name, Location__c,End_Date__c,Createddate 
FROM Order__c 
where Location__r.OwnerId=:00560000004LFQkAAO 
AND (Status ='Test' AND Createddate = LAST_N_MONTHS:6) LIMIT 1000';

Excepted Query String at Run time:


'SELECT Id, Name, Location__c,End_Date__c,Createddate 
FROM Order__c 
where Location__r.OwnerId='00560000004LFQkAAO'
AND (Status ='Test' AND Createddate = LAST_N_MONTHS:6) LIMIT 1000';


Work Around Solution
Remove bind variable from query string and add single quotes before and after the user id

public void fetchOrders()
{
List<Order__c> listOrders = new List<Order__c>();
String selWOStatus ='Test'  // Usually value for this comes from visual force page

String qry ='SELECT Id, Name, Location__c,End_Date__c,Createddate FROM Order__c where 
           Location__r.OwnerId=\''+UserInfo.getUserId()+'\'';
                        
if('All'.equalsIgnoreCase(selWOStatus))
  qry + = ' AND (Createddate =LAST_N_MONTHS:6 OR End_Date__c < NEXT_N_MONTHS:6) LIMIT 1000'; 

else
  qry + =' AND (Status =\''+String.escapeSingleQuotes(selWOStatus)+'\' 
         AND Createddate = LAST_N_MONTHS:6) LIMIT 1000';

System.debug('qry....'+qry); 

listOrders  = Database.query(qry);

System.debug('listTSOOrders....'+listOrders);

}


Thanks for visiting...Enjoy!

How To Fetch Next 6 Months or Last 6 Months Records From Salesforce

If your trying to fetch records from Salesforce based on some date values likes today ,tomorrow,last few days/months/weeks/years or next few days/months/weeks/years we can make use of the Salesforce Date Literals to simplify the SOQL query as much as possible and each literal is a range of time beginning with midnight (12:00:00).



Below sample code will explains you how to build a dynamic SOQL query using NEXT_N_MONTHS and LAST_N_MONTHS date literals to fetch Next 6 months and Last 6 Months records from Salesforce.

Sample Code:


public void fetchOrders()
{
List<Order__c> listOrders = new List<Order__c>();
String selWOStatus ='Test'  // Usually value for this comes from visual force page

String qry ='SELECT Id, Name, Location__c,End_Date__c,Createddate FROM Order__c where 
           Location__r.OwnerId=\''+UserInfo.getUserId()+'\'';
                        
if('All'.equalsIgnoreCase(selWOStatus))
  qry +=' AND (Createddate =LAST_N_MONTHS:6 OR End_Date__c < NEXT_N_MONTHS:6) LIMIT 1000';
  
else if('Open'.equalsIgnoreCase(selWOStatus))
  qry +=' AND (End_Date__c < NEXT_N_MONTHS:6 AND (Status !=\'Closed\' AND 
         Status !=\'Canceled\' AND Status !=\'Converted\')) LIMIT 1000';
    
else
  qry +=' AND (Status =\''+String.escapeSingleQuotes(selWOStatus)+'\' 
         AND Createddate = LAST_N_MONTHS:6) LIMIT 1000';

System.debug('q....'+qry); 

listOrders  = Database.query(qry);

System.debug('listTSOOrders....'+listOrders);

}


Thanks for visiting...Enjoy!

Friday, June 24, 2016

How To Write a SOQL To Fetch All Events Related to Account and Opportunity

Scenario:

Usually when we are writing any kind of SOQL queries on related objects we always known that this particular child record always be linked to specified parent object record. For example if you have a relationship between Account(Parent) and Contact(child) that means every contact record is related any one the account record not to any ABC__c or BCD__c objects.

But where in case of Task or Events if you could see we can't guarantee that these Tasks or Events are always related to a Account records or Contact Records because these Task or Events can be linked to any one of the Contract,Campaign,Account,Opportunity,Product,Asset,Case,Solution,Quote and Any Custom Objects .

Question:
In such type of situations the Task or Event that is linked to which object it's not a static and it's gets varies based on the Event that your creating for which object(Called as Polymorphic Relationship).Now If you want to fetch all Events related to Account and Opportunity only.How we need to write a SOQL query ?



Solution:

We already know that WhatId filed in Event or Task for deciding for which object this is linked /created.So with the help of TYPE qualifier on WhatId we can achieve this.The TYPE qualifier on field always determine the object type that is referenced for Task or Event.Use this TYPE clause on where condition of SOQL to control the result.

SELECT Id,subject,What.Type,whatId 
FROM Event
WHERE What.Type IN ('Account', 'Opportunity')

This above SOQL query returns all the Events related to Account and Opportunity only.


You can also apply comparison operators such as '=' or LIKE on WHERE condition of TYPE clause .


[SELECT Id,subject,What.Type,whatId 
FROM Event
WHERE What.Type like '%Accou%']

[SELECT Id,subject,What.Type,whatId 
FROM Event
WHERE What.Type ='Position__c']

They are multiple other ways also to do same.So we will discuss all those things in my next post.

Thanks for visiting...Enjoy!!!


What is Polymorphic Relationship in Salesforce ?

We are all very familiar with relationships in Salesforce right? Usually when we are discussing about relationships in salesforce immediately in our mind below listed relationship will appears

  • Lookup Relation Ship (Many-One relationship)
  • Master-detail Relationship  (Many-One relationship)
  • Many-to-Many Relationship
  • Self Relation Ship
But apart from this in salesforce we have one more relationship called Polymorphic Relationship.In all the above relationship (except Polymorphic Relationship) we always know that this particular child record always be linked to specified parent object record. For example if you have a relationship between Account(Parent) and Contact(child) that means every contact record is related any one the account record not to any ABC__c or BCD__c objects.

But where in case of Task or Events if you could see we can't guarantee that these Tasks or Events are always related to a Account records or Contact Records because these Task or Events can be linked to any one of the Contract,Campaign,Account,Opportunity,Product,Asset,Case,Solution,Quote and Any Custom Objects .These types of relationships is called as Polymorphic Relationship.In Polymorphic Relationship the referenced object of relationship can be any one of the Standard or Custom Objects.

Linking an attachment to any one of the custom object or standard object with the help of the Parent Id also refereed as Polymorphic Relationship only.

When your working with Polymorphic Relationship objects in SOQL we have several ways to access.

Follow my next to post to learn how to use this Polymorphic Relationship in SOQL.


Thanks for visiting....Enjoy!

Friday, March 18, 2016

How to write a SOQL Query to fetch yesterday created from an object

If you want to fetch yesterday created records from any salesforce object you can make use of the 'yesterday' standard keyword in SOQL to get it done easily.



Sample Query to fetch From Task

Select id,whoid,whatId,status from Task where createddate=yesterday


OutPut From Developer Console


Enjoy......!!!!

Thursday, February 4, 2016

How to Know Which Edition of Salesforce Your Using?

As we already know that there are different types of editions available in salesforce. Based upon the editions that you purchased you will be getting the features of salesforce. To know which editions currently your using we can use below ways to know it very easily.

Approaches

1. Mouse over on any browser tab where salesforce has been open then it will displays edition name which your using as shown below image



2. Write a SOQL query on Organisation object to get the edition name
 


3. Goto the Company information details and there you look for Organisation Edition(Only for Sandbox)


Enjoy........!!!

How to Delete the Records Permanently from the Recycle Bin in Salesforce

Basically in salesforce when you have deleted any record from an object, it will not be deleted permanently and it will be stored in Recycle bin till 15 days from the deletion date.The number of records stored in recycle bin depends on Number of Licenses your organisation has pursed and multiply it with 5000 records.
If the number of records in recycle bin crosses this limit salesforce automatically deletes the old records from Recycle Bin which are at least in recycle bin for 2 hours.If you want to delete the records permanently from recycle bin before salesforce deletes it you can emptyRecylebin() method.


     EmptyRecycleBinResult[] = DataBase.emptyRecyclebin(List of Ids)

Example:

    1. Account Acc = new Account(Id='0016000000I549m');
        Database.emptyRecycleBin(Acc);


Notes:

1. Maximum number of records per call that we can pass is 200
2. Using this function records deleted can not be undeleted again.
3. Theses deleted records from recycle bin can be accessed using the DataBase.queryAll() for some time typically that would be with in 24 hours or may shorter or longer.

Monday, January 4, 2016

System.QueryException: unexpected token: 'where'

Whenever you’re making any dynamic query construction in apex we will be ending with many errors .Among them one common error is System.QueryException: unexpected token: 'where' 

Code Snippet:
 String queryString = 'Select id,name,industry,';  
 queryString = queryString +'From Account';  
 System.debug('queryString ..'+queryString);  
 Database.query(queryString);  

When I run above code snippet I'm receiving System.QueryException: unexpected token: 'where' and then I checked my debug for the query it's something like as below

Debug value : Select id,name,industry, From Account

WorkAround 

 The extra comma in between Industry and From is causing the issue so if you remove that extra comma it will work perfectly.

Modified Code Snippet:
 String queryString = 'Select id,name,industry ';  
 queryString = queryString +'From Account';  
 System.debug('queryString ..'+queryString);  
 Database.query(queryString);  

So when ever your making dynamic quires please keep below points in mind

 1. Any extra commas are coming in queries
 2. Whether space is provided between last column and FROM statement
 3. Give space between From and Object Name

Got the solution....Enjoy..........!