简体   繁体   English

Linq制作效率非常低的Entity Framework查询

[英]Linq making very inefficient Entity Framework query

Entity Framework generates very poorly performing SQL for the following LINQ query: 实体框架为以下LINQ查询生成性能非常差的SQL:

var query = _context.Sessions
                    .Where(s => s.OrganizationId == orgId && s.Device != null && s.Device.User != null)
                    .Select(s => s.Device.User)
                    .Distinct();

Generates this SQL: 生成这个SQL:

exec sp_executesql N'SELECT
[Distinct1].[Id] AS [Id], 
[Distinct1].[Email] AS [Email], 
[Distinct1].[Sex] AS [Sex], 
[Distinct1].[Age] AS [Age]
FROM ( SELECT DISTINCT 
    [Extent4].[Id] AS [Id], 
    [Extent4].[Email] AS [Email], 
    [Extent4].[Sex] AS [Sex], 
    [Extent4].[Age] AS [Age]
    FROM   (SELECT [Extent1].[OrganizationId] AS [OrganizationId], [Extent3].[UserId] AS [UserId1]
        FROM   [dbo].[Sessions] AS [Extent1]
        INNER JOIN [dbo].[Devices] AS [Extent2] ON [Extent1].[DeviceId] = [Extent2].[Id]
        LEFT OUTER JOIN [dbo].[Devices] AS [Extent3] ON [Extent1].[DeviceId] = [Extent3].[Id]
        WHERE [Extent2].[UserId] IS NOT NULL ) AS [Filter1]
    LEFT OUTER JOIN [dbo].[Users] AS [Extent4] ON [Filter1].[UserId1] = [Extent4].[Id]
    WHERE [Filter1].[OrganizationId] = @p__linq__0
)  AS [Distinct1]',N'@p__linq__0 int',@p__linq__0=2

The SQL I'm actually looking to execute is the following, which runs lightning fast: 我实际上想要执行的SQL是以下,它快速运行:

select distinct u.*
from Sessions s
inner join Devices d on s.DeviceId = d.Id
inner join Users u on d.UserId = u.Id
where OrganizationId = 2

How can I get the Entity Framework-generated SQL to be as close to this query as possible? 如何让Entity Framework生成的SQL尽可能接近此查询?

Why select the whole User entity if you just want the email? 如果您只想要电子邮件,为什么选择整个User实体?

Try this: 尝试这个:

var query = _context.Sessions
                    .Where(s => s.OrganizationId == orgId && s.Device != null && s.Device.User != null)
                    .Select(s => s.Device.User.Email)
                    .Distinct();

Try starting with the users table: 尝试从users表开始:

var query = (
    from u in _context.Users
    where u.Devices.Any(d => d.Sessions
        .Any(s => s.OrganisationId == orgId)
    )
    select u
);

It won't do the query you specified but what it does return might have the same good performance. 它不会执行您指定的查询,但它返回的内容可能具有相同的良好性能。

You can do it pretty simply: 你可以很简单地做到:

_context.Sessions
    .Where(s => s.OrganizationId == 2)
    .Select(s => s.Device.User)
    .Distinct();

You do not need to check for null , as it will perform an INNER JOIN for you. 您不需要检查null ,因为它将为您执行INNER JOIN

I dont like use the DISTINCT , if a query contains it then the query's wrong. 我不喜欢使用DISTINCT,如果查询包含它,那么查询是错误的。

Other way to do it 其他方式来做到这一点

var query = _context.Sessions.Include("Device.User.Email")
                    .Where(s => s.OrganizationId == orgId);

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

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