I’m working with EF Core 6 and PostgreSQL, and I need to construct a query that efficiently retrieves author names along with an array of their book titles.
My database schema:
Books
- BookId (number)
- AuthorId (number)
- BookName (string)
Authors
- AuthorId (number)
- AuthorName (string)
The SQL query I’m trying to achieve is:
SELECT Authors.AuthorName, array_agg(Books.BookName)
FROM Authors
JOIN Books ON Books.AuthorId = Authors.AuthorId
GROUP BY Authors.AuthorId
Since EF Core 6 doesn’t directly support array_agg
, how can I translate this into C# LINQ to SQL while prioritizing performance?
Here’s what I’ve tried so far:
C#
from a in context.Authors
join b in context.Books
on a.AuthorId equals b.AuthorId
group b.BookName by a.AuthorId into g
select new
{
AuthorId = g.Key,
BookNames = g.Select(name => name).ToList()
};
Currently everything I tried when using Group By translated to join and then another leftJoin.
Is there a way for me to add a translation to array_agg
?
Any help or suggestions would be greatly appreciated!
2
Answers
At the end I have created a view on top of the table with a migration. Then I used the view as a regular table in my code. That way I didn't need to "play" with EF too much.. The only downside is that for every change I need to change the view manually in SQL in a migration.
Link for how to use views in EF core: https://medium.com/@niteshsinghal85/creating-views-with-entity-framework-core-9383a9a80543
It’s pretty easy to just add your own custom translator for
array_agg
. In EF Core 7 this has now been added, but you can create a custom one yourself.Copying bits from the official code, you first need a function you can put into the expression
Then a translator to create a
SqlExpression
from the queryExpression
tree.Then a plugin to offer up that translator. You will add this to your ServicesCollection via Dependency Injection:
You add it to the ServiceCollection
Then you can use it in your query like this