简体   繁体   English

为什么这个LINQ查询无法正常工作?

[英]Why does this LINQ query fail to work?

I am running into a problem that I like to understand why it is happening. 我遇到了一个我喜欢理解它为什么会发生的问题。 Some help would be appreciated. 一些帮助将不胜感激。

I am using entity framework core and this is the query I have in my code: 我正在使用实体框架核心,这是我在我的代码中的查询:

var user = await _db.User
      .Where(x => x.Email == username & x.Suspended == null)
      .Select(x => new
      {
           x.UserId,
           x.Password,
           x.Salt,
           Role = x.Role.Name
      })
      .SingleOrDefaultAsync();

在此输入图像描述
This query does not select the user but it doesn't throw any error ether. 此查询不会选择用户,但不会抛出任何错误以太。 If I remove "x.Suspended" from Where clause than it will return the user. 如果我从Where子句中删除“x.Suspended”而不是它将返回用户。 The "Suspended" is a table that is related to the user table by the user ID. “Suspended”是一个通过用户ID与用户表相关的表。 The user ID is PKs in both tables, so the relation is 1 to 1. I think this query does not return the user because the x.Suspended is null. 用户ID是两个表中的PK,因此关系是1到1.我认为此查询不返回用户,因为x.Suspended为null。 Can some one help me understand why this is happening and what I can do to make it work. 有人可以帮助我理解为什么会发生这种情况以及我能做些什么来使其发挥作用。

UPDATE: Ok, I used SQL server profiler and this is the converted sql by entity framework: 更新:好的,我使用SQL服务器分析器,这是实体框架转换的SQL:

exec sp_executesql N'SELECT [x.Suspended].[UserId], [x.Suspended].[RCD], [x.Suspended].[Reason], [x].[UserId], [x].[Password], [x].[Salt], [x.Role].[Name]
FROM [User] AS [x]
INNER JOIN [Role] AS [x.Role] ON [x].[RoleId] = [x.Role].[RoleId]
INNER JOIN [Suspended] AS [x.Suspended] ON [x].[UserId] = [x.Suspended].[UserId]
WHERE [x].[Email] = @__username_0',N'@__username_0 varchar(80)',@__username_0='some-username'

the problem here is that all one-to-one relations are converted to INNER JOINs. 这里的问题是所有一对一关系都转换为INNER JOIN。 How can I handle this problem? 我该如何处理这个问题? Thanks in advance! 提前致谢!

UPDATE 2: I am starting to think that this is a bug in EF Core. 更新2:我开始认为这是EF Core中的一个错误。 For example when I have this: 例如,当我有这个:

var user = await _db.User
      .Include(x => x.Role)
      .Include(x => x.Suspended)
      .Where(x => x.Email == username)
      .SingleOrDefaultAsync();

Under profiler the sql output is this: 在profiler下,sql输出是这样的:

exec sp_executesql N'SELECT TOP(2) [x].[UserId], [x].[Email], [x].[FirstName], [x].[LastName], [x].[Password], [x].[Phone], [x].[RCD], [x].[RoleId], [x].[Salt], [s].[UserId], [s].[RCD], [s].[Reason], [r].[RoleId], [r].[Name]
FROM [User] AS [x]
LEFT JOIN [Suspended] AS [s] ON [s].[UserId] = [x].[UserId]
INNER JOIN [Role] AS [r] ON [x].[RoleId] = [r].[RoleId]
WHERE [x].[Email] = @__username_0',N'@__username_0 varchar(80)',@__username_0='user-email'

Clearly the "Suspended" table is left join not inner. 很明显,“暂停”表是连接而不是内部。 But when I have this: 但是当我有这个:

 var user1 = await _db.User
       .Include(x => x.Role)
       .Include(x => x.Suspended)
       .Where(x => x.Email == username & x.Suspended == null)
       .SingleOrDefaultAsync();

The sql under the sql profiler is: sql profiler下的sql是:

SELECT [x].[UserId], [x].[Email], [x].[FirstName], [x].[LastName], [x].[Password], [x].[Phone], [x].[RCD], [x].[RoleId], [x].[Salt], [x.Suspended].[UserId], [x.Suspended].[RCD], [x.Suspended].[Reason], [s].[UserId], [s].[RCD], [s].[Reason], [r].[RoleId], [r].[Name]
FROM [User] AS [x]
INNER JOIN [Suspended] AS [x.Suspended] ON [x].[UserId] = [x.Suspended].[UserId]
LEFT JOIN [Suspended] AS [s] ON [s].[UserId] = [x].[UserId]
INNER JOIN [Role] AS [r] ON [x].[RoleId] = [r].[RoleId]

what a mess :-D how the hell do we have "Suspended" table joined twice, INNER and LEFT? 真是一团糟:-我们到底怎么会有“暂停”牌桌加入两次,INNER和LEFT? And where is the WHERE clause? WHERE子句在哪里?

All I want is this in LINQ to work: 我想要的只是在LINQ中工作:

SELECT U.[UserId], U.[Password], U.[Salt], R.[Name] AS [Role]
FROM [ag].[dbo].[User] AS U
INNER JOIN [ag].[dbo].[Role] AS R ON U.[RoleId] = R.[RoleId]
LEFT JOIN [ag].[dbo].[Suspended] AS S ON U.[UserId] = S.[UserId]
WHERE U.[Email] = 'john.smith@gmail.com' AND S.[UserId] IS NULL

You should use && 你应该使用&&

var user = await _db.User
      .Where(x => x.Email == username && x.Suspended != null)
      .Select(x => new
      {
           x.UserId,
           x.Password,
           x.Salt,
           Role = x.Role.Name
      })
      .SingleOrDefaultAsync();

I was right on this, it is a bug and will be fixed in the future EF core releases. 我是对的,这是一个错误,将在未来的EF核心版本中修复。 Here is the link to the issue on github . 这是github上的问题的链接。

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

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