2011-11-23 34 views
10

我試圖強制Linq在兩個表之間執行內部連接。我會舉一個例子。強制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 ... 
) 

現在,我有不尋常的數據庫工作作爲是有原因的超出了我的控制,爲人們從人民表中缺少但在CompanyPositions的記錄。我想通過加入表格來過濾掉缺少People的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(); 

但是,現在在我的SQL中創建了一個不必要的where子句。作爲最純粹的我想刪除這個。任何想法或當前的數據庫設計是否與我的手一致?

+1

你在使用? LINQ to SQL? LINQ to Entities?還有別的嗎? – svick

+1

您的模型是否具有導航屬性?如果是這樣,你可以寫一些像'where pos.Person!= null'。 – svick

+0

我正在使用LinqToSql,我試過'where pos.Person!= null'和'p.PersonId!= 0',Linq刪除它們。在'p.PersonId!= 0'的情況下,它將其更改爲'pos.PersonId!= 0',即使它不是我所追求的,也會給我留下深刻的印象。 – Magpie

回答

2

由於PERSONID聲明NOT NULL(我假設它被聲明爲FK以人),那麼我不知道你如何擁有一個沒有被分配的人的公司位置; Linq看不到你怎麼看,這就是爲什麼你觀察到Linq認爲這個連接是多餘的。

+1

這很有道理,我正在使用的數據庫是一個更大更復雜的大師的扁平化版本。只有與一種產品相關的數據纔會被轉發給這個和唉,因爲這些缺失的記錄中沒有FK,這些都在主設備上執行。在這種情況下,該人員已被取消發佈,因此不會被主人推送。理想情況下,公司地位也不會,但這是我無法控制的。看起來db設計是這裏的主要問題。 – Magpie

0

如果您正在使用LinqToSql,您可以使用LoadWith與此類似:

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

我不知道如何強制linq使用連接。但是下面的表述應該會給你所需的結果。

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

客戶方的轉換:

(
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