C# 在EF Core中将实体映射到DTO之后,Distinct如何处理IQueryable?

C# 在EF Core中将实体映射到DTO之后,Distinct如何处理IQueryable?,c#,entity-framework-core,C#,Entity Framework Core,我对我们的数据库运行了一个类似于此的查询: var result = await _context.MyEntities .Select(x => new SubEntityDto { Id = x.SubEntity.Id }) .Distinct() .ToListAsync(); 实体子实体可以是多个MyEntity上设置的同一实体 因为我想要一个无重复项的子实体数据列表,所以我在生成的IQueryable上运行.Distinct()。这是SubEntity

我对我们的数据库运行了一个类似于此的查询:

var result = await _context.MyEntities
    .Select(x => new SubEntityDto { Id = x.SubEntity.Id })
    .Distinct()
    .ToListAsync();
实体
子实体
可以是多个
MyEntity
上设置的同一实体

因为我想要一个无重复项的
子实体数据列表,所以我在生成的
IQueryable
上运行
.Distinct()
。这是
SubEntityDto
类:

public class SubEntityDto
{
    public int Id { get; set; }
}
这是可行的,但我不知道在使用DTO时,它是如何使列表变得清晰的。在这种情况下,
.Distinct()
是否使用
.Equals
方法?
.Equals
是否默认为reference equality,它检查两个实例是否为同一实例

如果我从数据库加载列表,然后执行
Distinct()
,它将不再工作,如下所示:

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

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

我认为它在为SQL查询创建SQL时设法做到了这一点,但是有人能告诉我发生了什么吗?我感到困惑的是,在实体映射到DTO后,它似乎会跟踪它们。

正如您问题的注释中提到的,当您创建查询时,它会被您的提供者转换为SQL查询。因此,在第一种情况下,它是
Queryable.Distinct()
,而在第二种情况下,您已经通过调用
ToListAsync()
对数据库运行了查询,并且查询结果已经转换为内存中的DTO(对象)。因此运行
Enumerable.Distinct()

您还可以使用调试器查看创建的查询

您可以通过放置一个断点,然后调查变量DebugView的内容来查看提供者创建的查询→查询→文本可视化工具将显示结果。

这两个查询没有任何共同之处。其中一个被转换为SQL,特别是
从子实体中选择不同的Id…
。第二个使用
Object.Equals
,除非
SubEntityDto
重载它以查找重复项。在没有重载的情况下,它只比较引用注意,第一个
Distinct()
Queryable.Distinct()
,而第二个
Enumerable.Distinct()
,因此第一个
Distinct()
是您正在构建的查询的一部分。啊,我明白了。因此,即使
Distinct()
Select
之后,它也会被转换成SQL?我猜,
Select
没有转换为SQL,因此它实际上会根据需要重新排列语句。
var distinctSubEntities=subEntities.Distinct().ToList();//不清楚。
您会发现它是。。。但这不是你想做的。。。。它因记忆而不同。你想做一个类似于distinct(x=>x.Id)的distinct BX,但这并不存在,所以你必须自己写。。您可以看看,它添加了一系列有用的操作,您会感兴趣的是Distinct第一个操作之所以有效,是因为它在DbContext上完成并转换为sql DISTINCTAlright,但是它是否重新排列了Select和Distinct?Select在Select DISTINCT SQL查询之后运行,我找不到与您在屏幕截图中显示的相同的、漂亮的SQL视图。它隐藏在哪里?进一步检查后,似乎
选择
将查询更改为只返回
子实体
。我还没有找到此操作的文档。@ptf,您可以通过放置断点,然后调查变量DebugView的内容来查看提供程序创建的查询→查询→文本可视化工具将显示结果。我也更新了我的答案。我也不理解您关于使用Select更改查询的问题。如果您愿意,我们可以开始聊天,然后再谈。不用担心,谢谢:)