I'm new to salesforce, apex and visualforce so please forgive me if I'm asking a dumb question.

I'd like to have into a visualforce page a list of all events and related account (if any) of the current user. For that, if I understood correctly, the easiest way is to have a custom Wrapper Object that encapsulate Event and Account.

Now, the problem is how to populate the list of the EventAccountWrapper list in an elegant way. I think it could be done with only one SOQL query with a Right Outer Join but the polymorphic entity of Event.whatId relation with the Account is making my brain to crash out.

Right now this is what I'm doing:

  1. retrive all events
  2. find out all events whatid property
  3. retrive all accounts that are in what ids
  4. cycle through all the events and construct the wrapper object

Right now this is my actual code inside the controller:

public class EventAccountWrapper {
    public Account account { get; private set; }
    public Event event { get; private set; }
    public eventAccountWrapper(Event e, Account a) {
        this.account = a;
        this.event = e;

public EventAccountWrapper[] eventAccounts {
    get {
        List<EventAccountWrapper> ret = new List<EventAccountWrapper>();

        Event[] events = [
            select subject,whatid,startdatetime,enddatetime 
            from event
            where ownerid =: UserInfo.getUserId()];

        List<Id> whatIds = new List<Id>();
        for(Event e : events) {
        Map<Id, Account> accounts = new  Map<Id, Account>([
            select id, name, phone 
            from account
            where account.id in :whatIds]);

        for(Event e : events) {
            EventAccountWrapper w;
            if( accounts.containsKey(e.whatid) ) {
                w = new EventAccountWrapper(e, accounts.get(e.whatid));
            } else {
                w = new EventAccountWrapper(e, null);
        return ret;
    private set;

How can I optimize it?

1 Answer 1


One immediate optimization that jumps out is that you should lazy load your query data. As it stands, every time you call the getter on your eventAccounts property, it runs two queries. Here is how you would lazy load your Event query.

public List<Event> events
        if (events == null)
            events = [
                SELECT Subject, WhatId, StartDatetime, EndDatetime 
                FROM Event
                WHERE OwnerId = :UserInfo.getUserId()
        return events;
    private set;

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .