3

在职的:

我正在尝试在我的Contacts表和我的Permissions表之间执行 LEFT OUTER JOIN。我有这个正常工作的基础,无论他们是否有相应的权限,都可以取回联系人列表。

// Query for Contacts
from contact in Contacts
join permission in Permissions on contact.Id equals permission.ObjectId into permissionGrp
from p in permissionGrp.DefaultIfEmpty()            
where p==null || (p!=null && /* ... condition based on the existence of a permission */)
select new { contact, permission = p };

生成 WHERE SQL:

WHERE
(t1.PermissionId IS NULL OR 
    ((t1.PermissionId IS NOT NULL AND ... other conditions ... )))

问题:

我想修改上述内容以引入“后备”检查;没有按预期工作。

要求:

  • 当没有Permission对应的Contact(ie p==null) 时,则只包含基于预定bool值的行allowed

试图:

我以为我可以这样做where (p==null && allowed) || ...

// Fallback permission
bool allowed = false;

// Query for Contacts
from contact in Contacts
join permission in Permissions on contact.Id equals permission.ObjectId into permissionGrp
from p in permissionGrp.DefaultIfEmpty()

/* Added bool condition 'allowed' to control inclusion when 'p' is null */
where (p==null && allowed) || (p!=null && /* ... condition based on the existence of a permission */)
select new { contact, permission = p };

预期的:

何时allowed = false(不接受null许可)

WHERE
    ((t1.PermissionId IS NOT NULL AND ... other conditions ... ))

何时allowed = true (接受null许可)

WHERE
(t1.PermissionId IS NULL OR 
    ((t1.PermissionId IS NOT NULL AND ... other conditions ... )))

实际结果:

总是输出好像allowed=false什么时候true

WHERE
    ((t1.PermissionId IS NOT NULL AND ... other conditions ... ))

概括:

我希望我只是在做一些很容易解决的愚蠢的事情。
如何null根据给定bool值过滤我的值记录?

4

2 回答 2

1

我怀疑我正在使用的 ORM ( LightSpeed )中存在错误,我会提请他们注意。

解决方法

我找到了一个合适的解决方法,使用该let子句。

// Fallback permission
bool allowed = false;

// Query for Contacts
from contact in Contacts
join permission in Permissions on contact.Id equals permission.ObjectId into permissionGrp
from p in permissionGrp.DefaultIfEmpty()

/* Work around for 'allowed' not being honoured properly, using 'let' */
let isAllowed = allowed

/* Added bool condition 'isAllowed' to control inclusion when 'p' is null */
where (p==null && isAllowed) || (p!=null && /* ... condition based on the existence of a permission */)
select new { contact, permission = p };

结果

它现在使用已知值与自身的比较作为布尔检查。在这种情况下t0.ContactId

SQL 当allowed=true...t0.ContactId = t0.ContactId

WHERE
    ((t1.PermissionId IS NULL AND t0.ContactId = t0.ContactId) OR 
     (t1.PermissionId IS NOT NULL AND ... other conditions ...))

SQL 当allowed=false...t0.ContactId <> t0.ContactId

WHERE
    ((t1.PermissionId IS NULL AND t0.ContactId <> t0.ContactId) OR 
     (t1.PermissionId IS NOT NULL AND ... other conditions ...))
于 2013-11-25T11:37:39.170 回答
1

你在这里表演GroupJoin。所以第一部分的结果permissionGrp, 是一个匿名类型IGrouping<Permission>。这已经是 OUTER JOIN 的等价物了。

您可以通过有条件地测试是否IGrouping<Permission>包含元素来实现您想要的:

from contact in Contacts
join permission in Permissions on contact.Id equals permission.ObjectId
    into permissionGrp
where allowed || g.Any()
from p in permissionGrp.DefaultIfEmpty()
select new { contact, permission = p };

请注意,from p in permissionGrp再次展平分组,因此.DefaultIfEmpty()对于allowed == true.

于 2013-11-25T08:36:18.557 回答