Entity Framework linq to sql проблема преобразования - PullRequest
0 голосов
/ 01 февраля 2019

Борьба с EF6 / linq to SQL, чтобы получить желаемый результат.Я бы предпочел не создавать представление в базе данных.

Есть идеи, почему EF преобразует его таким образом или как его обмануть?

Мой предикат linq:

.Where(x => 
   (x.AccountId == viewModel.AccountId || x.AccountId == null)
   && (x.CompanyId == viewModel.CompanyId || x.Company == null)
   && (x.FacilityId == viewModel.FacilityId || x.FacilityId == null)
)

Сгенерированный SQL:

WHERE 
   (([Extent1].[AccountId] = 1) 
    OR (([Extent1].[AccountId] IS NULL) AND (1 IS NULL)) 
    OR ([Extent1].[AccountId] IS NULL)
   ) 
   AND 
   (
    ([Extent1].[CompanyId] = 11) 
    OR (([Extent1].[CompanyId] IS NULL) AND (11 IS NULL)) 
    OR ([Extent2].[Id] IS NULL)
   ) 
   AND 
   (
    ([Extent1].[FacilityId] = 1) 
    OR (([Extent1].[FacilityId] IS NULL) AND (1 IS NULL)) 
    OR ([Extent1].[FacilityId] IS NULL)
   )  
   AND 
   (
    ([Extent1].[FacilityId] = 1) 
    OR (([Extent1].[FacilityId] IS NULL) AND (1 IS NULL))
   )

SQL, который я думал получить, и достиг желаемого результата:

WHERE 
(
    ([Extent1].[AccountId] = 1) 
    OR ([Extent1].[AccountId] IS NULL)
) 
AND 
(
    ([Extent1].[CompanyId] = 11) 
    OR ([Extent2].[Id] IS NULL)
) 
AND 
(
    ([Extent1].[FacilityId] = 1) 
    OR ([Extent1].[FacilityId] IS NULL)
) 

1 Ответ

0 голосов
/ 01 февраля 2019

Пожалуйста, попробуйте:

.Where(x => 
   (x.AccountId == (int)viewModel.AccountId || x.AccountId == null)
   && (x.CompanyId == (int)viewModel.CompanyId || x.Company == null)
   && (x.FacilityId == (int)viewModel.FacilityId || x.FacilityId == null)
)

Или:

var accountId = viewModel.AccountId.GetValueOrDefault();
var companyId = viewModel.CompanyId.GetValueOrDefault();
var facilityId = viewModel.FacilityId.GetValueOrDefault();
...
...
.Where(x => 
   (x.AccountId == accountId || x.AccountId == null)
   && (x.CompanyId == companyId || x.Company == null)
   && (x.FacilityId == facilityId || x.FacilityId == null)
)

Ваш исходный запрос ссылался на обнуляемые типы в качестве параметров, поэтому EF необходимо было создать предикат, который мог работать предсказуемокогда значение вашего параметра равно нулю, поэтому вы увидите дополнительные ([Extent1].[AccountId] IS NULL) AND (@p__linq__0 IS NULL).Приведя ваши параметры к типу подчеркивания в вашем запросе (в данном случае System.Int32), EF не увидит необходимости делать это, потому что он "думает", что ваш параметр не может быть нулевым.

Все этонеобходим, потому что по умолчанию ваше соединение с сервером SQL будет иметь опцию ANSI_NULLS, это означает, что любое сравнение с NULL будет ложным, и поэтому EF необходимо сгенерировать эту дополнительную логику (оператор IS NULL), чтобы обеспечитьчто вы можете получить предсказуемые результаты, когда значение вашего параметра равно нулю.

Вы можете попробовать это, чтобы увидеть эффекты ANSI_NULLS в действии:

SET ANSI_NULLS ON;
SELECT 1 WHERE NULL = NULL;

SET ANSI_NULLS OFF;
SELECT 1 WHERE NULL = NULL;
...