Salesforce can give some pretty unhelpful errors at time. This one isn't the clearest, but if you pause for a moment and take a good look at it, it starts to make sense.
Besides the line number, this is the most important part of the error:
must be a concrete SObject: List
So somewhere, on that line, Salesforce is expecting an SObject
, but you're giving Salesforce a List
.
We know it's on line 4. A SOQL query returns a List
, and you're storing the result in a List
, so there's no problem there (you actually don't need to use the List
constructor here, or do any casting for that matter, but that's beside the point).
The only other place on line 4 that can be causing your error is this:
where name in :b.account__c
If we take a look at the lines above, b
is defined as a List<Book__c>
. This fits the error that you're getting. b
is a List
, but using dot notation to reference a field is something that needs to be done on an SObject
.
Your list stored in b
does contain Book__c
records (Book__c
is also an SObject
), so to be able to access the Account__c
field, you need access to one of the actual records in your list (for which you'd use [<some integer>]
or .get(<some integer>)
).
At the very least (and I do emphasize that this is the very least you could do), to make this work, you'd do the following
// I've omitted the rest of the query for brevity
// Notice how we use square brackets before trying to reference the field
// Apex is 0-indexed, meaning the first item in the array is at index 0 (instead of 1)
where name in :b[0].account__c];
Keith C's answer goes over better practices for accomplishing what you're looking to do.