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
Venkat NithinVenkat Nithin 

How to check for an existing relationship between two Contact records

In our org we have some piece of apex code which allows users to create a related contact to an existing contact. It can be done by clicking a button on the custom related list situated at the bottom of the contact record.

 

The problem I am facing is, users are able to create multiple relationships with same contact. And also a contact can be linked to itself as well. I solved the second part saying if the Ids of two records are same, dont create the relation.

 

But the tricky one is the first part. There is a junction object called Contact_connector in between them. which is inserted everytime the relation is created. If there is a way to put in both the existing record Id and duplicated record and tranverse through the Contact_connectorID and check if thats existing then I can say dont create.

 

But am not finding a way to check whether the Contact_connectorId exists between them.

Would be a great help if any one can come up with a solution..

Best Answer chosen by Admin (Salesforce Developers) 
PremanathPremanath

If you want for update operation also simply add  before update  like

trigger TriggerExistingRelation on SFDC_Contact_Connector__c (before insert,before update) {

}

 

But as per your requirement entire code is wrong. It won't work for Insert oparetion also.

 

Why because your requirement is to check the  two records are same or not, But here in if condition your writing code for taking all record values but not perticular record.

 

 

 //Get the list
    List<SFDC_Contact_Connector__c> relrecs = [Select cl.Contact__c, cl.Related_Contact__c from  SFDC_Contact_Connector__c cl where cl.Id  IN :relids];
    
    set<id> ContactsSet = new set<id>();
    for(SFDC_Contact_Connector__c cl: relrecs)
    {
        ContactsSet.add(cl.Contact__c);
    }
    set<id> RelContsSet = new set<id>();
    for(SFDC_Contact_Connector__c cl: relrecs)
    {
        RelcontsSet.add(cl.Related_Contact__c);
    }

 

 

 

 if(ContactsSet.contains(cl.Contact__c) && RelContsSet.contains(cl.Related_Contact__c))

 

for Example:-

 

cricket is junction object

Batsman and Bowlers are parents

 

Here i am creating two records in Cricket object

 

Cricketname1

sachin

Zaheer

 

Cricketname2

dravid

sreenth

 

 

The Next record should be allow if it is like this

 

Cricketname3

sachin

sreenth

 

But your code Doesn't allow this record why because it is checking all two record values

 

So here you have to check the values are in the same record are not


At the time only   Cricketname3  record will allow.

 

 

So instead of set use map here

 

 

Map<id,id> ContactsSet = new Map<id,id>();

Map<id,id> RelContsSet = new Map<id,id>();
    for(SFDC_Contact_Connector__c cl: relrecs)       // use one loop is enough
    {
        ContactsSet.put(cl.Contact__c,cl.id);

        RelcontsSet.add(cl.Related_Contact__c,cl.id );
    }

 

So here Key is Different But Values are same

In if condition based on value(record id) you can check and then only return error

 

Better to use System.Debug();       For every step then your can find the errors easily

 

See some Map examples and follow up

 

 

Prem

 

 

 

 

All Answers

PremanathPremanath

First thing you have to write a trigger Before insert event

 

In that trigger wrte a query for take all Records from Contact_connector.

 

Take two lists for that  two look-up fields : contact and Child_contact , Both are bringing id only.

 

Now Whatever your inserting the record in Contact_connector, That will come to Trigger.New

 

Then Use if condition to check whether the same values are in the list or not.

If it is available return Error Message. Else it should be save.

 

 

Thanks

Prem

 

Venkat NithinVenkat Nithin

Thank you very much Prem..

 

That makes sense to me, will try doing that..

 

 

Cheers

Ven

Venkat NithinVenkat Nithin

Hi Prem.. I have written the following trigger.. 

 

trigger TriggerExistingRelation on SFDC_Contact_Connector__c (before insert) {
    //Get all the Existing Relationship Record Ids
    SFDC_Contact_Connector__c[] relconts = [Select Id, Contact__c, Related_Contact__c from SFDC_Contact_Connector__c];
    set<id> relids = new set<id>();
    for(SFDC_Contact_Connector__c cl : relconts)
    {
    relids.add(cl.Id);
    }
    //Get the list 
    List<SFDC_Contact_Connector__c> relrecs = [Select cl.Contact__c, cl.Related_Contact__c from  SFDC_Contact_Connector__c cl where cl.Id  IN :relids];
    
    set<id> ContactsSet = new set<id>();
    for(SFDC_Contact_Connector__c cl: relrecs)
    {
        ContactsSet.add(cl.Contact__c);
    }
    set<id> RelContsSet = new set<id>();
    for(SFDC_Contact_Connector__c cl: relrecs)
    {
        RelcontsSet.add(cl.Related_Contact__c);
    }
    for(SFDC_Contact_Connector__c cl: Trigger.new)
    {
    try{
     if(ContactsSet.contains(cl.Contact__c) && RelContsSet.contains(cl.Related_Contact__c))
     {
        cl.addError('A relationship already exists with the same person');
        }
    }
    catch (Exception ex){
        // do nothing
       }
    }
}

 

It is working, But the problem is It is not allowing to create any new relationship with the existing records. Eg: If B is related to A and if I want to relate B to another record C it is not allowing me to do so..

If I choose list then I cant use contains function. So am confused of what to do now.. Is there any other way of checking all the existing records if they contain the pair of Contact Id and Related Contact Id

PremanathPremanath

If you want for update operation also simply add  before update  like

trigger TriggerExistingRelation on SFDC_Contact_Connector__c (before insert,before update) {

}

 

But as per your requirement entire code is wrong. It won't work for Insert oparetion also.

 

Why because your requirement is to check the  two records are same or not, But here in if condition your writing code for taking all record values but not perticular record.

 

 

 //Get the list
    List<SFDC_Contact_Connector__c> relrecs = [Select cl.Contact__c, cl.Related_Contact__c from  SFDC_Contact_Connector__c cl where cl.Id  IN :relids];
    
    set<id> ContactsSet = new set<id>();
    for(SFDC_Contact_Connector__c cl: relrecs)
    {
        ContactsSet.add(cl.Contact__c);
    }
    set<id> RelContsSet = new set<id>();
    for(SFDC_Contact_Connector__c cl: relrecs)
    {
        RelcontsSet.add(cl.Related_Contact__c);
    }

 

 

 

 if(ContactsSet.contains(cl.Contact__c) && RelContsSet.contains(cl.Related_Contact__c))

 

for Example:-

 

cricket is junction object

Batsman and Bowlers are parents

 

Here i am creating two records in Cricket object

 

Cricketname1

sachin

Zaheer

 

Cricketname2

dravid

sreenth

 

 

The Next record should be allow if it is like this

 

Cricketname3

sachin

sreenth

 

But your code Doesn't allow this record why because it is checking all two record values

 

So here you have to check the values are in the same record are not


At the time only   Cricketname3  record will allow.

 

 

So instead of set use map here

 

 

Map<id,id> ContactsSet = new Map<id,id>();

Map<id,id> RelContsSet = new Map<id,id>();
    for(SFDC_Contact_Connector__c cl: relrecs)       // use one loop is enough
    {
        ContactsSet.put(cl.Contact__c,cl.id);

        RelcontsSet.add(cl.Related_Contact__c,cl.id );
    }

 

So here Key is Different But Values are same

In if condition based on value(record id) you can check and then only return error

 

Better to use System.Debug();       For every step then your can find the errors easily

 

See some Map examples and follow up

 

 

Prem

 

 

 

 

This was selected as the best answer
Venkat NithinVenkat Nithin

Thank you very much Prem.. That was a great help.

 

A new concern came up now.. We do have millions of Relationship records in our org.. My trigger works fine in the sandbox  but am worried about putting that onto the production, because a single query is going to return millions of record rows and may bounce into governor limits.. Whats the best way to limit the rows regarding this?? Is there a standard salesforce approach or Is that concern with our org??

Venkat NithinVenkat Nithin

Is there any way to search for the related contacts of the new record contacts..?? using relationship queries or anything as such?..

PremanathPremanath

For Newly created contact , how can you create/present the child records.

clearly explain what is your requirement.

 

if you want for related contacts means

  List<Contact> varex=[select id,name,(select id,name from child_Contact__r) from Contact where Id in :Trigger.old];

  if(varex.size()==0){

  //message

}

else{

   //return varex records ;

}

 

 

Venkat NithinVenkat Nithin

I will explain my requirement by the following cricket example.

 

Suppose I have players - sachin, Zaheer, Sreeshanth, Gambir, Raina ( which are already existing).

The trigger i am trying to wirte is for creating a relationship for existing contacts..

 

Existing Relations would be 

Cricket1 - Sachin & Zaheer

Cricket2 - Sachin & Sreeshanth

Cricket3 - Gambir & Zaheer .........etc.

 

If another relationship is required with sachin - It should allow - Sachin & Raina.

where as if users by mistake try to relate Sachin & Zaheer agina that should fail. This is my requirement.

 

In the first approach you suggested.. 

 SFDC_Contact_Connector__c[] relconts = [Select Id, Contact__c, Related_Contact__c from SFDC_Contact_Connector__c];

This is fetching all the relationship records and checking them against the new ones..

 

But there are more than a million reocrds in our org.. So firing this trigger would bounce into governor limits..

 

So now what I think is.. instead of fetching all the relationship records..

If relationship is to create between Sachin and Raina..

Get the existing relatioships on Sachin and existing relationships on Raina and check whether any of them match..

 

If it matches then display error..

 

Would be a great help if you could suggest a solution for this.. Thanks in advance

 

PremanathPremanath

Hi Venkat,

 

  Good Idea, But you must write query here, If sachin having more than 50,000 records at that time also you cross governor limits.

if it is not a problm means you can go through this way.

 

string str1,str2;

 for(SFDC_Contact_Connector__c cl: Trigger.New)
{
        str1=cl.cContact__c;

        str2=cl.Related_Contact__c;
}

 

List<SFDC_Contact_Connector__c> relrecs = [Select cl.Contact__c, cl.Related_Contact__c from  SFDC_Contact_Connector__c cl where cContact__c=str1 ];

 

Map<id,id> ContactsSet = new Map<id,id>();

Map<id,id> RelContsSet = new Map<id,id>();
    for(SFDC_Contact_Connector__c cl: relrecs)   
    {
        ContactsSet.put(cl.Contact__c,cl.id);

    }

 

List<SFDC_Contact_Connector__c> relrecs123 = [Select cl.Contact__c, cl.Related_Contact__c from  SFDC_Contact_Connector__c cl where cContact__c=str2 ];

 

for(SFDC_Contact_Connector__c cl: relrecs123)   
    {
        ContactsSet.put(cl.Related_Contact__c,cl.id);

    }

 

 

Here you get the id's of those existing records. then you can compare the id's , if it is same then display error.

 

 

===========================

 

But one simple way we have.

 

If we write query for checking two values are there in one record or not. like this

 

 

string str1,str2;

 for(SFDC_Contact_Connector__c cl: Trigger.New)
{
        str1=cl.cContact__c;

        str2=cl.Related_Contact__c;
}

 

List<SFDC_Contact_Connector__c> relrecs = [Select cl.Contact__c, cl.Related_Contact__c from  SFDC_Contact_Connector__c cl where cContact__c=str1 and Related_Contact__c=str2];

 

if(relrecs.size()>0){

// Error

}

else

//allow save

 

 

This is good Enough Right!!!!

 

 

 

 

Prem

 

Venkat NithinVenkat Nithin

Thanks very much Prem.. I understood the solution.. but when am trying to save the trigger.. It is showing error for 'Contact__c = str1'

Error: Compile Error: unexpected token: 'str1

 

It is not accepting the reference as string.. Is it because the Contact is Id?

PremanathPremanath

Write like this

Contact__c =:str1

 

trigger TriggerExistingRelation on Cricket__c (before insert,before update) {
    //Get all the Existing Relationship Record Ids
    /*Cricket__c[] relconts = [Select Id, Batsman__c, Bowler__c from Cricket__c];
    set<id> relids = new set<id>();
    for(Cricket__c cl : relconts)
    {
    relids.add(cl.Id);
    }
    //Get the list 
   // List<Cricket__c> relrecs = [Select cl.Batsman__c, cl.Bowler__c from  Cricket__c cl where cl.Id  IN :relids];
    
    set<id> ContactsSet = new set<id>();
    for(Cricket__c cl: relrecs)
    {
        ContactsSet.add(cl.Batsman__c);
    }
    set<id> RelContsSet = new set<id>();
    for(Cricket__c cl: relrecs)
    {
        RelcontsSet.add(cl.Bowler__c);
    }*/
    String str1,str2;
    for(Cricket__c cl: Trigger.new)
    {
        str1=cl.Batsman__c;
        str2=cl.Bowler__c;
        /*System.Debug(cl.Bowler__c+'===================================='+cl.Batsman__c);
         if(ContactsSet.contains(cl.Batsman__c) && RelContsSet.contains(cl.Bowler__c))
         {
            cl.addError('A relationship already exists with the same person');
         }*/
    }
    List<Cricket__c> relrecs = [Select Batsman__c,Bowler__c from  Cricket__c where Batsman__c=:str1 and Bowler__c=:str2];
    if(relrecs.size()>0){
       Trigger.New[0].addError('A relationship already exists with the same person');
    }
    
    
}

 

Venkat NithinVenkat Nithin

Sorry my ignorance.. didnt notice that.. as am a apex starter..

 

Thats perfectly working..

 

That was really a great help Prem.. Thank you very much.. Thanks a lot..