为什么这个LINQ查询无效?

时间:2016-10-23 03:17:01

标签: c# linq async-await entity-framework-core

我遇到了一个我喜欢理解它为什么会发生的问题。一些帮助将不胜感激。

我正在使用实体框架核心,这是我在代码中的查询:

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();

enter image description here
此查询不会选择用户,但它不会抛出任何错误以太。如果我删除" x.Suspended" from Where子句比它将返回用户。 "暂停"是一个用户ID与用户表相关的表。用户ID是两个表中的PK,因此关系为1到1。 我认为此查询不会返回用户,因为x.Suspended为null。有人可以帮助我理解为什么会这样,以及我能做些什么来使它发挥作用。

更新: 好的,我使用的是SQL server profiler,这是按实体框架转换的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'

这里的问题是所有一对一关系都转换为INNER JOIN。我该如何处理这个问题?提前谢谢!

更新2: 我开始认为这是EF Core中的一个错误。例如,当我有这个:

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

在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'

显然"暂停"表是左连接而不是内部。但是当我有这个:

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

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]
什么是混乱:-我们到底怎么了"暂停"表连接两次,INNER和LEFT? WHERE子句在哪里?

我想要的只是在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

2 个答案:

答案 0 :(得分:0)

您应该使用&&

{{1}}

答案 1 :(得分:0)

我是对的,这是一个错误,将在未来的EF核心版本中修复。以下是 github 上问题的链接。