2011-11-23 12 views
10

Próbuję zmusić Linq do przeprowadzenia wewnętrznego połączenia między dwoma tabelami. Dam przykład.Wymuszanie linq do wykonywania połączeń wewnętrznych

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 ... 
) 

Teraz pracuję z niezwykłej bazie danych, ponieważ nie jest to powód, poza moją kontrolą, by ludzie mogli być brakuje tabeli ludzi, ale posiada rekord w CompanyPositions. Chcę odfiltrować CompanyPositions z brakującymi osobami, dołączając do tabel.

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

Linq traktuje to sprzężenie jako zbędne i usuwa je z generowanego przez siebie kodu SQL.

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

Jednak w moim przypadku nie jest to zbyteczne. Mogę to naprawić tak:

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

Jednak teraz to tworzy niepotrzebną klauzulę where w moim SQL. Jako najczystsze chciałbym to usunąć. Każdy pomysł czy obecny projekt bazy danych wiążą moje ręce?

+1

Czego używasz? LINQ do SQL? LINQ do jednostek? Coś innego? – svick

+1

Czy Twój model ma właściwości nawigacyjne? Jeśli tak, możesz napisać coś takiego: 'where pos.Person! = Null'. – svick

+0

Używam LinqToSql, próbowałem "gdzie pos.Person! = Null" i "p.PersonId! = 0" i Linq je usuwa. W przypadku "p.PersonId! = 0" zmienia się na "pos.PersonId! = 0", co robi na mnie wrażenie, nawet jeśli nie jest to coś, do czego dążę. – Magpie

Odpowiedz

2

Od PersonID deklaruje NOT NULL (i zakładam, że jest zadeklarowana jako FK ludziom), a następnie nie jestem pewien jak możesz mieć CompanyPosition z osobą, która nie jest przypisana; i Linq nie może zobaczyć, jak możesz sobie z tym poradzić, dlatego, jak zauważyłeś, Linq uważa, że ​​dołączenie jest zbędne.

+1

To ma sens, baza danych, z którą pracuję, to spłaszczona wersja znacznie większego i bardziej skomplikowanego mistrza. Tylko dane odnoszące się do jednego produktu są przekazywane do tego i niestety, z powodu takich brakujących rekordów nie ma żadnych FK, są one egzekwowane na kapitanie. W tym przypadku osoba nie została opublikowana, więc nie została wypchnięta od mistrza. Idealnie nie byłoby również CompanyPosition, ale to jest poza moją kontrolą. Wygląda na to, że głównym problemem jest projekt db. – Magpie

0

Jeśli używasz LinqToSql, można użyć LoadWith podobnego do tego:

var context = new MyDataContext(); 
var options = new DataLoadOptions(); 
options.LoadWith<People>(x => x.CompanyPositions); 
context.LoadOptions = options; 
0

Nie wiem, jak wymusić na Linq korzystanie z łączenia. Jednak poniższe informacje powinny dać ci wymagany wynik.

return (from pos in CompanyPositions 
     where (p in People select p.PersonId).Contains(pos.PersonId) 
     select pos).ToList(); 
0

stronie klienta transformacja:

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

bardziej bezpośrednia filtracja:

from pos in CompanyPositions 
where pos.People.Any() 
select pos 
Powiązane problemy