Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SelectMany on list/array types should translate to unnest #1525

Open
FiniteReality opened this issue Oct 7, 2020 · 4 comments
Open

SelectMany on list/array types should translate to unnest #1525

FiniteReality opened this issue Oct 7, 2020 · 4 comments
Labels
enhancement New feature or request
Milestone

Comments

@FiniteReality
Copy link

I have a C# query which looks something like this:

var validGuildIds = new[] { 1, 2, 3, 4 };
await _authDbContext.Groups
    .Where(group => group.GuildIds.Any(x => validGuildIds.Contains(x)))
    .SelectMany(x => x.GuildIds)
    .ToArrayAsync();

The goal is to find any rows with a GuildIds column which contains an element from validGuildIds, since I later want to invert that query and show the user only elements from validGuildIds which weren't found in the database.

Following the docs, I'd expect this query to expand to something like this, using parametrised queries as appropriate:

SELECT unnest("GuildIds") FROM "Groups" WHERE "GuildIds" && ARRAY[1, 2, 3, 4];

However, I instead get an exception that the expression x => x.GuildIds could not be translated.

My project is configured to use Npgsql.EntityFrameworkCore.PostgreSQL version 5.0.0-rc1, since that's the latest on NuGet.

@roji
Copy link
Member

roji commented Oct 8, 2020

Translating top-level SelectMany is a complex task that would require changes in the EF Core as well.

However, your array intersection operation does translate, so you can work around this by executing the SelectMany on the client as below. The WHERE clause gets executed on the server, which is the important part - it doesn't really matter if the "merging" projection happens on the server or on the client.

var results = ctx.Groups
    .Where(group => group.GuildIds.Any(x => validGuildIds.Contains(x)))
    .AsEnumerable()
    .SelectMany(x => x.GuildIds)
    .ToArray();

(use System.Interactive.Async for async client-side LINQ operators)

Leaving open to track implementing this in the future at some point.

@roji roji added this to the Backlog milestone Oct 8, 2020
@roji roji added the enhancement New feature or request label Oct 8, 2020
@evilz
Copy link

evilz commented Jan 24, 2023

What about a EF.Functions.unnest special function ?

@roji
Copy link
Member

roji commented Jan 24, 2023

@evilz that wouldn't necessary reduce the complexity of the translation.

@roji
Copy link
Member

roji commented Jan 24, 2023

I'll put this on 8.0 as a possible improvement (but there's a good chance I won't get around to it...)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants