I have CustomObject__c that has the standard Owner field (which is a lookup field to a User). My code is the following:

User myUser;

//assume I've populated myUser as a result of a SOQL query or something and it points to a real user in my org

CustomObject__c newCustObj = new CustomObject__c(Name = 'My New Obj', OwnerId = myUser.Id);

At this point newCustObj.Owner.Email will be null.

However, if I insert this object to the database, and then query for it using something like [SELECT Name, Owner.Email FROM CustomObject__c WHERE Id = 'abc123'] Then I will be able to properly access that email field.

How can I access the email field right away after I instantiate the object? I do not want to save it to the DB at that point. Just keep it in memory.

Thanks, Danny


It looks like you cannot do that for any Object's whose OwnerId field has its namePointing value set to true. The namePointing indicates that the Owner field can be polymorphic (e.g., Lookup(User,Queue)). The technical documentation on the namePointing attribute is:

Indicates whether the field's value is the Name of the parent of this object (true) or not (false). Used for objects whose parents may be more than one type of object, for example a task may have an account or a contact as a parent.

The Name object documentation is:

This object is used to retrieve information from related records where the related record may be from more than one object type (a polymorphic foreign key). For example, the owner of a case can be either a user or a group (queue). This object allows retrieval of the owner name, whether the owner is a user or a group (queue). You can use a describe call to access the information about parents for an object, or you can use the who, what, or owner fields (depending on the object) in SOQL queries. This object cannot be directly accessed.

Knowing this, it makes sense that it would not be writeable, because you would be assigning a User to a Name object.

It appears that you can query the User record and then assign it directly to the Owner field on the Object that has the OwnerId field and namePointing false (such as Account and Contact). At that point, it will be available in memory. Note that if you insert/update the record that has the Owner value set, the Owner value will go away, and you'll have to query it back out.

Here is an example that uses Account:

User u = [Select Id, Email From User][0];
Account acct = new Account(Name = 'Test', Owner = u, OwnerId = u.Id);

System.assertEquals(u.Email, acct.Owner.Email);
  • Thanks for the snippet Peter. Indeed your snippet compiles fine. However, when I simply swap out Account for my CustomObject__c, I get the error "Field is not writeable: Owner". This Owner field is the one that came automatically when I created my object, and there does not appear to be anything I can do to modify its "writeability"...
    – Danny
    Apr 10 '14 at 1:56
  • The plot thickens: If I use a custom object but instead of the Owner field, I use a custom field of Master-Detail type, then I CAN do something along the lines of what you suggest like so: CustomObject__c newObj = new CustomObject__c(Name = 'Test Obj', customMasterDetailField__r = u, customMasterDetailField__c = u.Id); So it seems like perhaps only that default Owner field for custom objects (which goes away as soon as you create a custom Master-Detail field for that object), which is of type "Lookup(User, Queue)" is not working
    – Danny
    Apr 10 '14 at 2:05
  • Yeah. Just experimented. I believe it is allowed when the Owner field is Lookup(User), like it is on Account and Contact, but not allowed when it is Lookup(multiple objects), e.g., Lookup (User, Queue). Apr 10 '14 at 2:11
  • Thanks Peter for the comprehensive investigation. And your original suggestion did help me in a different case where I was using a regular Master-Detail field and successfully assigned the __r version to the record with the desired result.
    – Danny
    Apr 10 '14 at 4:34

You will have to query for the Email address. Adding to the code you have it would be:

String email = [select Email from User where Id = :myUser.Id].Email;

But obviously if you are querying earlier in your code for information about User you can include the Email field then.

Note that if all you want to access is the id value (and a few other values) of the logged in User, you can directly use the static methods of the UserInfo class. This includes UserInfo.getUserEmail() for the Email address. (It is not clear in your question if the User you are making the Owner is an arbitrary User or the logged in User.)

  • The problem is that I have a VF page that displays a CustomObject__c in a <apex:pageBlockTable>. One of the columns I show is Owner.Email. So, if I have loaded a particular CustomObject__c from the DB, it properly shows the e-mail in the table. But, if I instantiate a new CustomObject__c, even if I assign it a valid User Id as its OwnerId property, it does not show the email in the table. Does that clarify the issue?
    – Danny
    Apr 9 '14 at 23:45
  • @Danny Yes it does. I think you can assign a reference to the User object myUser to the relationship called Owner of your custom object. That wouldn't result in the relationship being persisted - you have to assign OwnerId for that - but I think it will keep your Visualforce happy.
    – Keith C
    Apr 9 '14 at 23:57
  • No such luck unfortunately - if I try to do newCustObj.Owner = myUser; it gets angry ("Illegal assignment from SOBJECT:User to SOBJECT:Name")
    – Danny
    Apr 10 '14 at 0:04
  • @Danny Sorry about that, but looks like you've got to the bottom of it in your thread with Peter. Looks like you are going to have to resort to the wrapper class bodge, where the wrapper holds references to both the CustomObject and related User.
    – Keith C
    Apr 10 '14 at 7:53

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.