question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Query: Translate Distinct to SQL when applied after custom projection

See original GitHub issue

I looked up for this problem and didn’t find anything. Sorry if I’m making a dup or I messed up something.

This

context.Blogs
    .Select(t => new BlogDto
    {
        Url = t.Url
    })
    .Distinct()
    .ToList();

resulted in the following query:

SELECT [t].[Url]
FROM [Blogs] AS [t]

and I expected:

SELECT DISTINCT [t].[Url]
FROM [Blogs] AS [t]   

So, now I’m using the following workaround:

context.Blogs
    .Select(t => new
    {
        Url = t.Url
    })
    .Distinct()
    .Select(t => new BlogDto
    {
        Url = t.Url
    })
    .ToList();

which results in:

SELECT [t1].[Url]
FROM (
    SELECT DISTINCT [t0].[Url]
    FROM [Blogs] AS [t0]
) AS [t1]

Steps to reproduce

    public class BlogDto
    {
        public string Url { get; set; }
    }

    public class BlogContext : DbContext
    {
        public DbSet<Blog> Blogs { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.UseSqlServer(@"Data Source=.;Initial Catalog=Blogging;Integrated Security=True;MultipleActiveResultSets=True");
            //optionsBuilder.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=CollectionsTest;Trusted_Connection=True;ConnectRetryCount=0");
        }
    }

    public class Program
    {
        private static void Main()
        {
            using (var context = new BlogContext())
            {
                var results = context.Blogs
                    .Select(t => new BlogDto
                    {
                        Url = t.Url
                    })
                    .Distinct()
                    .ToList();
            }
        }
    }

Just to be clear, the following works as expected:

context.Blogs
    .Select(t => new
    {
        Url = t.Url
    })
    .Distinct()
    .ToList();

produces:

SELECT DISTINCT [t].[Url]
FROM [Blogs] AS [t]

I have one simple question regarding terminology. When you say ‘projection’ (‘projecting’ to some object different from the model), does that include anonymous objects? If so, the title of this issue should be “Projecting to a specific object(class) with Distinct is not working as expected”

Thank you!

Further technical details

EF Core version: 1.1.0 Database Provider: Microsoft.EntityFrameworkCore.SqlServer Operating system: Win 8.1 64bit IDE: Visual Studio 2015 Update 3

Issue Analytics

  • State:closed
  • Created 7 years ago
  • Reactions:4
  • Comments:6 (5 by maintainers)

github_iconTop GitHub Comments

6reactions
divegacommented, Jan 4, 2017

EF Team Triage: We discussed this and we believe we should try to support this query and the translation to DISTINCT on the server.

2reactions
adzhiljanocommented, Dec 13, 2016

Thanks for the response! You are right, but when working with a DbContext, I personally think of Distinct(IQueryable) as a way to force a distinct to be executed on the server(query provider). I’m sure that a lot of people are used to this way of query construction.

Also, if you run the following using EF 6

context.Blogs
    .Select(t => new BlogDto
    {
        Url = t.Url
    })
    .Distinct()
    .ToList();

you will get the following translation:

SELECT 
    [Distinct1].[C1] AS [C1], 
    [Distinct1].[Url] AS [Url]
    FROM ( SELECT DISTINCT 
        [Extent1].[Url] AS [Url], 
        1 AS [C1]
        FROM [dbo].[Blogs] AS [Extent1]
    )  AS [Distinct1]

which is the same query as the one I mentioned in the workaround and again I think a lot of people are used to this mindset when constructing a query. It’s just confusing for me that somehow the server should be aware of comparing c# classes.

I saw the following

EF Core keeps the developer experience from EF6.x

at https://docs.microsoft.com/en-us/ef/efcore-and-ef6/ which is not true in this case. If you are transitioning from EF6 to EFCore you will have to refactor some of your queries including Distinct.

Even more, if you run:

context.Blogs
  .Distinct()
  .ToList();

you will get

SELECT DISTINCT [b].[BlogId], [b].[Url]
FROM [Blogs] AS [b]

and I didn’t find an override of the Equals method in the DbSet. Maybe I’m missing something conceptually or I’m just too used to EF6. Thanks, again!

Read more comments on GitHub >

github_iconTop Results From Across the Web

How to get COUNT DISTINCT in translated SQL with EF Core
Distinct ().Count() is now recognized by EF Core and translated to the corresponding SQL COUNT(DISTINCT expr)) , hence the original LINQ query ......
Read more >
Common use cases of SQL SELECT Distinct
This article will show the commonly used scenarios of SQL Select Distinct in an easily understandable format.
Read more >
Complex Query Operators - EF Core
Sometimes, a query in one form translates to the server but if written in a different form doesn't translate even if the result...
Read more >
Query MongoDB with SQL (GROUP BY, DISTINCT, JOINS ...
Here's how to query MongoDB with SQL using the SQL Query feature in Studio 3T. Supports SELECT, DISTINCT, GROUP BY, ORDER BY, JOINS, ......
Read more >
Custom queries, segmentation, and aggregation of session ...
Learn how you can access and query user session data based on keywords, syntax, functions, and more.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found