Принуждение linq для выполнения внутренних соединений - PullRequest
10 голосов
/ 23 ноября 2011

Я пытаюсь заставить Linq предварительно сформировать внутреннее соединение между двумя таблицами.Я приведу пример.

CREATE TABLE [dbo].[People] (
   [PersonId] [int] NOT NULL,
   [Name] [nvarchar](MAX) NOT NULL,
   [UpdatedDate] [smalldatetime] NOT NULL
   ... Other fields ...
)

CREATE TABLE [dbo].[CompanyPositions] (
   [CompanyPositionId] [int] NOT NULL,
   [CompanyId] [int] NOT NULL,
   [PersonId] [int] NOT NULL,
   ... Other fields ...
)

Сейчас я работаю с необычной базой данных, поскольку у меня есть не зависящая от меня причина, по которой люди пропускают таблицу People, но имеют запись в CompanyPositions.Я хочу отфильтровать CompanyPositions с отсутствующими людьми, присоединившись к таблицам.

return (from pos in CompanyPositions
        join p in People on pos.PersonId equals p.PersonId
        select pos).ToList();

Linq видит это объединение как избыточное и удаляет его из генерируемого им SQL.

SELECT 
[Extent1].[CompanyPositionId] AS [CompanyPositionId], 
[Extent1].[CompanyId] AS [CompanyId], 
.... 
FROM  [dbo].[CompanyPositions] AS [Extent1]

Однако это не такизбыточно в моем случае.Я могу исправить это следующим образом

// The min date check will always be true, here to force linq to perform the inner join
var minDate = DateTimeExtensions.SqlMinSmallDate;

return (from pos in CompanyPositions
        join p in People on pos.PersonId equals p.PersonId
        where p.UpdatedDate >= minDate
        select pos).ToList();

Однако теперь это создает ненужное условие where в моем SQL.Как чистейший я хотел бы удалить это.Любая идея или текущий дизайн базы данных связывает мои руки?

Ответы [ 4 ]

2 голосов
/ 23 ноября 2011

Поскольку PersonId объявлен NOT NULL (и я предполагаю, что он объявлен как FK для людей), то я не уверен, как вы могли бы создать CompanyPosition с человеком, который не назначен; и Linq не может видеть, как вы можете создать, поэтому, как вы заметили, Linq считает объединение избыточным.

0 голосов
/ 23 ноября 2011

ClientSide преобразование:

(
from pos in CompanyPositions
join p in People on pos.PersonId equals p.PersonId
select new {pos, p}
).ToList().Select(x => x.pos);

Больше прямой фильтрации:

from pos in CompanyPositions
where pos.People.Any()
select pos
0 голосов
/ 23 ноября 2011

Я не знаю, как заставить linq использовать соединение.Но следующий отчет должен дать вам требуемый результат.

return (from pos in CompanyPositions
        where (p in People select p.PersonId).Contains(pos.PersonId)
        select pos).ToList();
0 голосов
/ 23 ноября 2011

Если вы используете LinqToSql, вы можете использовать LoadWith, как показано ниже:

var context = new MyDataContext();
var options = new DataLoadOptions();
options.LoadWith<People>(x => x.CompanyPositions);
context.LoadOptions = options;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...