dotnet / efcore

EF Core is a modern object-database mapper for .NET. It supports LINQ queries, change tracking, updates, and schema migrations.
https://docs.microsoft.com/ef/
MIT License
13.8k stars 3.19k forks source link

Translate LINQ DistinctBy #27470

Open roji opened 2 years ago

roji commented 2 years ago

.NET 6.0 introduced DistinctBy, which we could translate.

DistinctBy can be rewritten as follows:

_ = blogs.DistinctBy(b => b.Id);

_ = blogs.GroupBy(b => b.Id).Select(g => g.First());

Note: since DistinctBy returns the first element with a given key, it is order-sensitive, and so we should issue a warning if it's used without OrderBy.

Note that PostgreSQL has a DISTINCT ON feature which is likely much more efficient than what we generate above (https://github.com/npgsql/efcore.pg/issues/894).

Jacko1394 commented 2 years ago

I cannot wait for this feature to work!! 👍

benmccallum commented 2 years ago

Would be cool to translate the following too, thought let me know if you want a separate issue.

_db.Posts
    .GroupBy(p => p.CategoryId)
    .Select(g => new
    {
        CategoryId = g.Key,
        NumberOfPosts = g.Count(),
        NumberOfTags = g.DistinctBy(p => p.TagId).Count()
   });

Though perhaps semantically this is a bit weird and the current way of doing it make more sense:

NumberOfTags = g.Select(p => p.TagId).Distinct().Count()
roji commented 2 years ago

@benmccallum yeah, just projecting first makes more sense to me: DistinctBy really is for when you want the actual entities, rather than just counting them afterwards.

lonix1 commented 4 months ago

Is this feature dependent on first handling all these issues?

roji commented 4 months ago

@lonix1 no; the above translation with GroupBy works at least in the basic case; there may be bugs in other, non-basic cases, but those don't prevent the basic transformation.

alainkaiser commented 3 weeks ago

Hi guys, are there any news on this? Thanks in advance for the feedback.

roji commented 3 weeks ago

No news at the moment.