簡體   English   中英

在LINQ WHERE子句中有條件地允許null

[英]Conditionally allowing for null in LINQ WHERE clause

工作:

我試圖在我的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 ... )))

問題:

我想改編以上內容來介紹'后備'檢查; 沒有按預期工作。

需求:

  • 當沒有對應於Contact Permission (即p==null )時,則僅包括基於allowed的預定bool值的行。

嘗試:

我以為我可以where (p==null && 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 ... )))

實際結果:

即使是true總是輸出,如果allowed=false

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

摘要:

我希望我只是做一些很容易修復的傻事。
如何根據給定的bool值過濾我的null值記錄?

您正在此處執行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再次展平分組,因此對於allowed == true的情況,仍然需要.DefaultIfEmpty()

我懷疑我正在使用的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 ...))

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM