7

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?

2 Answers 2

11

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.

1
  • 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
    Commented Mar 10, 2016 at 17:40
6

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);
}
3
  • Thanks for a more detailed answer, the detail is helpful, I had already selected the earlier answer as correct, but thanks again.
    – ScottH7a9
    Commented Mar 10, 2016 at 18:03
  • 1
    Probably Copy__c rather than Copies__c? Not clear based on OP but a more reasonable naming convention.
    – Adrian Larson
    Commented Mar 10, 2016 at 20:24
  • 2
    Yes, you're correct that convention is more typical. Updated the example.
    – Mark Pond
    Commented Mar 10, 2016 at 22:17

You must log in to answer this question.

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