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更改查询的问题。如果您愿意,我们可以开始聊天,然后再谈。不用担心,谢谢:)