2010-12-11 25 views
0

我试图创建一个“AssociateWith”数据加载选项为我的上下文筛选当前用户有权访问的行。我的简单的数据模型是这样:LINQ AssociateWith为数据上下文生成左连接,而不是INNER JOIN


UserPermissions
PK:ID
FK:RelatedUserID可空
FK:RelatedItemID不可为空

用户
PK:ID

项目
PK:ID
FK:RelatedCategoryID不能为空

分类 PK:ID

在我的datacontext,我试图做这样的事情:

//dbContext is my LINQ context 
//current_user_id is the id of my current logged in user 
var dlo = new DataLoadOptions(); 
//issue->UsersPermissions is one->many relationship 
// if I omit this LoadWith line, no associatewith filter 
// is created in the generated sql code 
dlo.LoadWith<Items>(i=>i.UserPermissions); 

dlo.AssociateWith<Items>(i=> 
i.UserPermissions.Where(p=> 
p.RelatedUserID.HasValue && p.RelatedUserID.Value == current_users_id)); 
dbContext.LoadOptions = dlo; 

一切似乎合理的给我,但在SQL生成的查询看起来像这样:

SELECT [t0].[ID], [t1].[ID] AS [ID2], [t1].[RelatedUserID], [t1].[RelatedItemID] 
(SELECT COUNT(*) 
FROM [dbo].[UserPermissions] AS [t2] 
WHERE (([t2].[RelatedUserID] = @p0)) AND ([t2].[RelatedItemID] = [t0].[ID]) 
) AS [value] 
FROM [dbo].[Items] AS [t0] 
LEFT OUTER JOIN [dbo].[UserPermissions] AS [t1] ON ([t1].[RelatedUserID] = @p0) 
AND  
([t1].[RelatedItemID] = [t0].[ID]) 
ORDER BY [t0].[ID], [t1].[ID] 

我该如何强制INNER JOIN而不是LEFT OUTER JOIN?我在后端上错误地建模了我的关系吗?

感谢您的任何帮助。

MMAS

回答

1

LINQ到SQL生成左外连接仅仅是因为UserPermissions.RelatedUserID列可以为空。底层的LINQ提供者不够“聪明”,不足以进一步将该查询优化为简单的INNER JOIN。我不认为你可以做任何事情。

+0

这正是我所担心的 - 如果你很好奇,它是可为空的原因是因为该表将最终引用另一个FK(可以称之为RelatedUsersCompanyID),也可为空,并在实践中无论是RelatedUserID或RelatedUsersCompanyID将始终提供。这个想法是,不是为每个有权访问项目的用户在用户表中添加一行,那么我们可以添加一行允许特定公司中的任何用户访问该项目。 有关我如何通过AssociateWith方法获得我想要的行为的任何明智想法,可用于此类数据模型? :) – Mustafakidd 2010-12-11 23:33:23

+0

难道你不能吐表中的用户和表的公司的UserPermissions表?通常应尽量减少数据库中可空列的数量。此外,你为什么使用'Associatewith'构建过滤器?是否有任何理由不只是做'过滤'通常'的方式(在LINQ查询中)? – Steven 2010-12-12 11:59:53

+0

我希望通过将过滤器构建到datacontext中来使开发人员更容易,因为我们几乎总是会过滤权限。不幸的是,我不知道为什么,即使我在需要的权限表上创建我的RelatedItemID,仍然会生成一个LEFT OUTER JOIN。不知道为什么在这种情况下... – Mustafakidd 2010-12-13 06:03:57