2

Upsert not working..update and insert not working..need help

I have tried using the example given in salesforce visual force developer guide for upsert. It just inserts a new row. I tried in a different way. It checks for a row with the name that matches the name on the page.if there is one rw , then it updates otherwise it will insert a new row. It works for insert but update does not work. I am putting both code here

Code from Salesforce developer guide. I copied the code as it is for page and class. It is not working.

public class NewAndExistingController {

    public Account account { get; private set; }

    public NewAndExistingController() {
        Id id = ApexPages.currentPage().getParameters().get('id');
        account = (id == null) ? new Account() :
            [SELECT Name, Phone, Industry FROM Account WHERE Id = :id];
    }

    public PageReference save() {
        try {
            upsert(account);
        } catch(System.DMLException e) {
            ApexPages.addMessages(e);
            return null;
        }
        //  After successful Save, navigate to the default view page
        PageReference redirectSuccess = new ApexPages.StandardController(Account).view();
        return (redirectSuccess);
    }
 }

My code: In getaccnt() method name is becoming null,update not working. if I use code in NewAndExistingController1() and insert works. If I comment that code , name is getting value and update is working but insert (upsert) does not work. If I put that code in else part, insert is not working. THis is killing me. I am not able to figur eout what is wrong. I needto do similar task for my client. Aready deadline is over. Please help.

public class NewAndExistingController1 
{
    public Account acc{get;set;}
    public string name {set; get;}
    public string phone {get; set;}
    //public string id {get; set;}
    public NewAndExistingController1() {
             system.debug('inside NewAndExistingController1' );
              Id id = ApexPages.currentPage().getParameters().get('id');
              system.debug('id' +id);
              acc = (id == null) ? new account() :  [select Id, Name, Phone, Industry from Account   WHERE Id = :id];
    }

    public boolean getcount() {
        integer ctr = [select count() from Account   WHERE Name = :name];
        system.debug('name= ' +name);
        system.debug('ctr = ' +ctr);
        return ctr == 1;
    } 


  public PageReference save() {
    try {

         // string    upd_flg =   [select 'X'  from Account   WHERE Name = :name];
         // this.acc = [select Id, Name, Phone from Account   WHERE Name = :name];


            if (getcount())
            {
                system.debug('check if getaccount');
                this.acc = [select Id, Name, Phone from Account   WHERE Name = :name];
                system.debug('acc' +acc.id);
                acc.phone = phone;
                update(acc);
                return null;
            }
            else
            {
                  system.debug('in else part');
                  // Id id = ApexPages.currentPage().getParameters().get('id');
                  // system.debug('id' +id);
                  // acc = (id == null) ? new account() :  [select Id, Name, Phone, Industry from Account   WHERE Id = :id];

                 //  account[] acc = [select Id, Name, Phone from Account   WHERE Name = :name];
                  // Account newAcct = new Account(Name = :Name,  phone = '54667788');
                    //acc.add(newAcct);

                    upsert acc;
                    return null;
            }
        }
        catch (exception ex)
        {
            ApexPages.Message msg = new ApexPages.Message(ApexPages.Severity.Error,    ex.getMessage());
            ApexPages.addMessage(msg);
            return null;
        }

    }
 }

Page code:

<apex:page controller="NewAndExistingController1" tabstyle="Account">
   <apex:form >
    <apex:pageBlock mode="edit">
        <apex:pageMessages />
        <apex:pageBlockSection >
            <apex:inputField value="{!acc.name}"/>
            <apex:inputField value="{!acc.phone}"/>
            <apex:inputField value="{!acc.industry}"/>
        </apex:pageBlockSection>
        <apex:pageBlockButtons location="bottom">
            <apex:commandButton value="Save" action="{!save}"/>
        </apex:pageBlockButtons>    
    </apex:pageBlock>
    </apex:form>
  </apex:page>
  • Can you put the business requirement to insert or update the Account record, rather than writing about insert/update not working – Santanu Boral Mar 30 '17 at 4:44
  • In NewAndExistingController.cls, you are not querying the Id field, could that be an issue? – Raul Mar 30 '17 at 4:48
  • @RahulSharma The ID field is automatically included in queries with the exception of queries made through the AJAX API. Outside of that instance you only need to query the ID when you are not querying additional fields (when Id is the only field you want). If you are referring to his aggregate query, Count() and Count(Id) are roughly the same. I believe count() is a bit more limited but I forget the exact circumstances developer.salesforce.com/docs/atlas.en-us.soql_sosl.meta/… – gNerb Mar 31 '17 at 2:37
0

Issue is in this method, here if the Name doesn't match then ctr=0 and it will return false and based on that you are updating in Save() operation. Thats the issue.

public boolean getcount() {
        integer ctr = [select count() from Account   WHERE Name = :name];
        system.debug('name= ' +name);
        system.debug('ctr = ' +ctr);
        return ctr == 1;
    } 

Ideally it will be like this:

public Integer getcount() {
    Tnteger ctr = [select count() from Account   WHERE Name = :name];
    system.debug('name= ' +name);
    system.debug('ctr = ' +ctr);
    return ctr;
} 


  public PageReference save() {
    try {
            //record exists
            if (getcount()>0)
            {
                system.debug('check if getaccount');
                this.acc = [select Id, Name, Phone from Account   WHERE Name = :name];
                system.debug('acc' +acc.id);
                acc.phone = phone;
                update(acc);
                return null;
            }
            else
            {
                //record doesn't exist
                system.debug('in else part');
                insert acc;
                return null;
            }
        }
        catch (exception ex)
        {
            ApexPages.Message msg = new ApexPages.Message(ApexPages.Severity.Error,    ex.getMessage());
            ApexPages.addMessage(msg);
            return null;
        }

    }
| improve this answer | |
  • He's using upsert, not update. upsert will insert new records as well. – gNerb Mar 30 '17 at 5:00
  • I have broken down based on his understanding – Santanu Boral Mar 30 '17 at 5:01
0

Properly Validating URL parameters:

The first thing I notice in your code is that you are not properly validating your ID parameter. You are only checking to make sure something is provided. You are not verifying the ID is valid let alone it is valid for account.

I'll provide an example class to help you out:

// This is an extremely simplified version of our Validator class.
// This should get you what you need for your immediate needs however you
// should investigate making your own.
public class Validator {
// Note: you should research how to get an objects
// prefix dynamically, in this instance I provided the account
// prefix to simplify things for you.
private static string prefix = '001';

public static Boolean validateId(String idToValidate) {
    if (idToValidate != null) {
        idToValidate = String.escapeSingleQuotes(idToValidate);
        Pattern idPattern = Pattern.compile('^[a-zA-Z0-9]*$');
        Matcher idMatcher = idPattern.matcher(idToValidate);

        if (idMatcher.matches() && 
            (
                idToValidate.length() == 15 ||
                idToValidate.length() == 18
            )
           ) {
            if (prefix != null) {

                if (idToValidate.left(3) == prefix) {
                    return true;
                } else {
                    return false;
                }
            } else {
                return true;
            }
        } else {
            return false;
        }
    } else {
        return false;
    }
}
}

Naming a variable the same as it's type:

In most programming languages this is completely invalid:

Id Id = ...;

A variable name should never match it's type. This may come down to a debate over preference because it is technically allowed in APEX; however, I would advise against it personally.

Account Name is Not Unique:

By Default, the Name field on account is not unique and should not be used for de-duping purposes - at least not exclusively. You can have two companies with the same name registered in different states that have nothing to do with each other. Not to mention internationally.

Too Many Queries:

Your code runs essentially the same query 3 times. This is against best practices a sit will literally triple your resource consumption. Remember SFDC is hosted in a tenant environment and the resources are shared across multiple organizations. You need to reduce your impact on the server as that is what all of the other developer's are doing for you.

Action Methods returning null page references:

If you do not intend to actually take advantage of the purpose of the page reference method, don't use it. Action methods can have a return type of void.

Taking all of the above into consideration, refactoring your code to adhere to best practices, and all of a sudden your issue doesn't exist:

public class NewAndExistingController1 {
public Account acc {get; private set;}

public NewAndExistingController1() {
    // Get this as a string, not an ID. This will help avoid exceptions in the event
    // that the value in the ID variable is invalid
    String accId = ApexPages.currentPage().getParameters().get('id');

    // This is a class we have that stores all of our validation logic for various data
    // types, I'd reccomend you make your own. If this bit is too complicated for you, stick with what you already have as it will probably work fine for you.
    // Additionally, I'm not using short hand as this makes the code a bit more unreadable
    // when you have a soql query in it.
    if (Validator.validateId(accId)) {
        acc = [
            SELECT Name, Phone, Industry
            FROM Account
            WHERE Id = :accId
        ];
    } else {
        acc = new Account();
    }
}

public void save() {
    // Use the ID to check if this is a pre-existing account. This wille
    // help reduce the number of queries you perform.
    // Visualforce binding does all the work for you here. You don't have to
    // explicitly set the data yourself
    try {
        if (acc.Id == null) {
            // If there is no Id (account id was not passed by the page)
            // Attempt to query for the ID
            // If there is still no ID after this line, the account is new
            acc.Id = [SELECT Id FROM Account WHERE Name = :acc.Name LIMIT 1].Id;
        }

        upsert acc;
        acc = new Account(); // Reset the account variable to clear the fields and allow for entering new data
        ApexPages.addMessage(new ApexPages.message(ApexPages.Severity.CONFIRM, 'Account Updated Successfully'));
    } catch (Exception e) {
        ApexPages.addmessage(new ApexPages.message(ApexPages.Severity.ERROR, e.getMessage()));
    }
}

Note: your VF code wont have to change, I just copied yours and used my controller and everything works.

| improve this answer | |
  • Thanks Toby. I copied your code . When I compiled I got the following error. I ried id instead i. Still got same error. Error: NewAndExistingController1 Compile Error: Variable does not exist: i at line 13 column 30 – SFDC Mar 30 '17 at 10:31
  • You may have copied the code while I was making edits to it. Please try to copy the current code and try again. I changed the variable name to accId as this is more descriptive and inline with best practices. – gNerb Mar 31 '17 at 2:34
  • Toby, It says update successfull, but creating two rows for same name. When I enter same name for Name field, and different phone number and/or different industry, and hit save, it creates new row for same name. Did you check the data if it is creating two rows for same name. I guess it is not getting Id from current page. When there is only one row for entered name, it should get id for that row. But it is not? – SFDC Apr 1 '17 at 14:59
  • I did leave out the de-duping because that's not a valid way to de-dupe accounts. I will add that back in for you but you really should look into how to properly de-dup. – gNerb Apr 2 '17 at 14:09
  • once you have a valid Id, id.getSobjectType() == Account.SObjectType tells you whether it is an Account ID and is more transparent. keyprefix is not required – cropredy Apr 3 '17 at 1:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.