Salesforce Stack Exchange is a question and answer site for Salesforce administrators, implementation experts, developers and anybody in-between. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

Using SOQL, I have two objects, Book__c and Copy__c, Copy is a child of Book. I run a query with a subquery to get copies associated with a book where the copy has a certain status.

The results are what I expect in the Query Editor, but I have trouble putting it into a List in Apex code.

List<Book__c> BookList = [SELECT Id, (SELECT Id, Status__c FROM Copies__r WHERE Status__c = 'Available') FROM Book__c];

This results in a list containing only the Book ID, none of the copy related fields are written to the List. If I change the List to any other data type I get told I can't convert from object type Book to String or whatever I am trying to use.

Can someone tell me the proper way to do this?

share|improve this question
up vote 7 down vote accepted

To access that list of Copies try using the following:

BookList[0].Copies__r

You should see some data if that query returned something.

You can also try to run your query in the query editor in the Developer Console you might understand it better then.

share|improve this answer
    
That did it, thanks. I did try it in the query editor and it worked fine, I just couldn't figure out the syntax to address it in the list. I thought it was only storing the Book information, but I see now this is how to address it to see the copy. Thanks again. – ScottH7a9 Mar 10 at 17:40

This query of yours produces an outer list, with a child list on each one of those outer list items.

List<Book__c> BookList = [SELECT Id
                            , Name
                                (SELECT Id
                                    , Name
                                    , Status__c 
                                FROM Copies__r 
                                WHERE Status__c = 'Available') 
                            FROM Book__c];

Visually you could represent it like this:

Book__c
    List<Copy__c>
Book__c
    List<Copy__c>
Book__c
    List<Copy__c>

In order to access the Copies children of each Book in this structure, you're going to use the __r relationship to access each List<Copy__c>. (__r is a List of your subquery)

In a loop, they can be accessed like this:

for (Book__c book : BookList) {
    system.debug('Book: ' + book.Name);

    for (Copy__c copy : book.Copies__r) {

        // output both the book name and the copy name
        system.debug('Book: ' + book.Name + ' - Copy: ' + copy.Name);
    }
}

You could also write your query from the perspective of the Copy__c object, which would return a different structure.

List<Copy__c> CopiesList = [SELECT Id
                                    , Name
                                    , Status__c
                                    , Book__r.Id // from the parent Book__c
                                    , Book__r.Name // from the parent Book__c
                                FROM Copy__c
                                WHERE Status__c = 'Available'];

In a similar loop, they can be accessed like this:

for (Copy__c copy : CopiesList) {

    // output both the book name and the copy name
    system.debug('Book: ' + copy.Book__r.Name + ' - Copy: ' + copy.Name);
}
share|improve this answer
    
Thanks for a more detailed answer, the detail is helpful, I had already selected the earlier answer as correct, but thanks again. – ScottH7a9 Mar 10 at 18:03
1  
Probably Copy__c rather than Copies__c? Not clear based on OP but a more reasonable naming convention. – Adrian Larson Mar 10 at 20:24
2  
Yes, you're correct that convention is more typical. Updated the example. – Mark Pond Mar 10 at 22:17

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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