2011-11-23 33 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