简体   繁体   English

从实体映射到 EF Core 中的 DTO 后,Distinct 如何在 IQueryable 上工作?

[英]How does Distinct manage to work on an IQueryable after mapping from entities to DTOs in EF Core?

I have a query similar to this that I am running against our database:我有一个类似的查询,我正在对我们的数据库运行:

var result = await _context.MyEntities
    .Select(x => new SubEntityDto { Id = x.SubEntity.Id })
    .Distinct()
    .ToListAsync();

The entity SubEntity can be the same entity set on multiple MyEntity .实体SubEntity可以是多个MyEntity上的同一实体集。

Since I want a list of SubEntityDto with no duplicates, I run .Distinct() on the resulting IQueryable<SubEntityDto> .因为我想要一个没有重复的SubEntityDto列表,所以我在生成的IQueryable<SubEntityDto>上运行.Distinct() This is the SubEntityDto class:这是SubEntityDto的 SubEntityD:

public class SubEntityDto
{
    public int Id { get; set; }
}

And this works, but I don't know how it manages to make the list distinct when working with the DTOs.这很有效,但我不知道在使用 DTO 时它如何使列表与众不同。 Doesn't .Distinct() use the .Equals method in this scenario? .Distinct()在这种情况下不使用.Equals方法吗? And doesn't .Equals default to reference equality, which checks whether two instances are the same instance? .Equals不默认引用相等,它检查两个实例是否是同一个实例?

If I load the list from the database, and then do Distinct() , it doesn't work anymore, like this:如果我从数据库加载列表,然后执行Distinct() ,它就不再起作用了,如下所示:

var subEntities = await _context.MyEntities
    .Select(x => new SubEntityDto { Id = x.SubEntity.Id })
    .ToListAsync();

var distinctSubEntities = subEntities.Distinct().ToList(); // Not distinct.

I'm thinking that it somehow manages to do this when creating the SQL for the SQL query, but can anyone tell me what is happening?我认为它在为 SQL 查询创建 SQL 时以某种方式设法做到这一点,但谁能告诉我发生了什么? I'm puzzled about the fact that it seems to keep track of the entites after they're mapped to DTOs.我很困惑这样一个事实,即它似乎在将实体映射到 DTO对其进行跟踪。

As mentioned in the comments to your question, when you create your query it gets translated into SQL query by your provider.正如对您问题的评论中提到的,当您创建查询时,您的提供商会将其转换为 SQL 查询。 So in the first case it is Queryable.Distinct() , however, in the second case you have already run your query against your database by calling ToListAsync() and result of it already translated to DTO's in memory (objects).因此,在第一种情况下它是Queryable.Distinct() ,但是,在第二种情况下,您已经通过调用ToListAsync()对数据库运行了查询,并且它的结果已经转换为 memory(对象)中的 DTO。 Therefore Enumerable.Distinct() is run.因此Enumerable.Distinct()运行。

You can also use your debugger to see the created query您还可以使用调试器查看创建的查询在此处输入图像描述

You can see the created query by your provider by putting a breakpoint and then investigating the contents of the variable DebugView→Query→Text Visualizer will show you the result.您可以通过放置断点来查看提供程序创建的查询,然后调查变量 DebugView→Query→Text Visualizer 的内容将显示结果。 在此处输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM