Linq to SQL присоединяется к пустым значениям, когда я этого не хочу - PullRequest
0 голосов
/ 10 мая 2018

Я написал следующий запрос, чтобы объединить пару таблиц. La.UserProfileId обнуляется по какой-то безбожной причине.

Когда я пишу эквивалентный оператор SQL, в этот момент я получаю 0 записей, как и должен.

var result = (from e in _ctx.Employees
                     join la in _ctx.LoginAudits on e.UserProfile.Id equals la.UserProfileId.Value
                     where la.LoginDate >= fromDate
                     && e.Client.Id == clientID
                     select new
                     {
                         la.Id,
                         employeeID = e.Id,
                         e.Client.DisplayName,
                         la.UserProfileId
                     }).ToList();

Приведенный выше код LINQ генерирует приведенный ниже SQL.

exec sp_executesql N'SELECT 
1 AS [C1], 
[Extent2].[Id] AS [Id], 
[Extent1].[Id] AS [Id1], 
[Extent3].[DisplayName] AS [DisplayName], 
[Extent2].[UserProfileId] AS [UserProfileId]
FROM   [dbo].[Employees] AS [Extent1]
INNER JOIN [dbo].[LoginAudits] AS [Extent2] ON ([Extent1].[UserProfile_Id] = [Extent2].[UserProfileId]) OR (([Extent1].[UserProfile_Id] IS NULL) AND ([Extent2].[UserProfileId] IS NULL))
INNER JOIN [dbo].[Clients] AS [Extent3] ON [Extent1].[Client_Id] = [Extent3].[Id]
WHERE ([Extent2].[LoginDate] >= @p__linq__0) AND ([Extent1].[Client_Id] = @p__linq__1)',N'@p__linq__0 datetime2(7),@p__linq__1 bigint',@p__linq__0='2018-02-09 11:11:29.1047249',@p__linq__1=37

Как видите, он включает в себя «ИЛИ (([Extent1]. [UserProfile_Id] IS NULL) И ([Extent2]. [UserProfileId] IS NULL))»

Это полная противоположность того, что я хочу. Как я могу сделать это сделать нормальное внутреннее соединение и не пытаться учесть нулевые значения?

Мне удалось обойти это, добавив && la.UserProfileId! = Null в мое предложение WHERE, но в идеале я бы предпочел, чтобы JOIN вел себя как обычный INNER JOIN, а не пытался предвидеть то, о чем я не прошу .

1 Ответ

0 голосов
/ 10 мая 2018

Это полная противоположность того, что я хочу. Как я могу заставить его делать нормальное внутреннее соединение и не пытаться учесть нулевые значения?

Причина в том, что в C # null == null оценивается как true, а в SQL - NULL (и в основном обрабатывается как FALSE). Поэтому EF пытается эмулировать поведение C #, чтобы получить тот же результат, как если бы вы выполняли тот же запрос в LINQ to Objects.

Это стандартное поведение EF6. Он управляется свойством UseDatabaseNullSemantics, поэтому, если вы хотите использовать поведение SQL, вам следует установить значение true в конструкторе производного класса DbContext или извне:

[dbContext.]Configuration.UseDatabaseNullSemantics = true;

Но этого недостаточно. Это влияет на все операторы сравнения, но они забыли применить его к объединениям. Решение состоит в том, чтобы не использовать оператор LINQ join, а коррелировать where (EF достаточно умен, чтобы превратить его в SQL JOIN).

В дополнение к установке UseDatabaseNullSemantics в true, замените

join la in _ctx.LoginAudits on e.UserProfile.Id equals la.UserProfileId

с

from la in _ctx.LoginAudits where e.UserProfile.Id == la.UserProfileId

и вы получите желаемое INNER JOIN.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...