ServiceStack ORM Lite左连接查询过滤失效问题求助
问题描述
使用ServiceStack ORM Lite对PurchaseInvoice和PurchaseInvoiceProjectLink做左连接后,尝试过滤出两种情况的记录:
PurchaseInvoiceProjectLink的ProjectId在用户权限项目列表内- 左连接无匹配记录(即
PurchaseInvoiceProjectLink为null)
但原代码中s == null的判断不生效,生成的SQL里该部分被转成了OR ('{}' is null),无法正确匹配左连接无结果的场景。原代码如下:
q = q.LeftJoin<PurchaseInvoice, PurchaseInvoiceProjectLink>((pi, pipl) => pi.Id == pipl.PurchaseInvoiceId); q = q.Where<PurchaseInvoiceProjectLink>(s => Sql.In(s.ProjectId, UserSession.ProjectIds) || s == null);
临时解决方案
目前通过屏蔽编译器警告的方式临时解决,但不想依赖#pragma:
#pragma warning disable CS0472 // The result of the expression is always the same since a value of this type is never equal to 'null' q = q.Where<PurchaseInvoiceProjectLink>(s => Sql.In(s.ProjectId, UserSession.ProjectIds) || s.PurchaseInvoiceId == null); #pragma warning restore CS0472
无需
#pragma的正确解决方案 方案1:使用Sql.IsNull判断关联表主键
直接通过Sql.IsNull指定关联表的主键字段,既不会触发编译器警告,又能生成正确的SQL:
q = q.LeftJoin<PurchaseInvoice, PurchaseInvoiceProjectLink>((pi, pipl) => pi.Id == pipl.PurchaseInvoiceId); q = q.Where<PurchaseInvoiceProjectLink>(s => Sql.In(s.ProjectId, UserSession.ProjectIds) || Sql.IsNull(s.PurchaseInvoiceId));
Sql.IsNull会被ORM Lite解析为PurchaseInvoiceId IS NULL,正好匹配左连接无结果的场景。
方案2:使用多表参数的Where重载
改用包含两张表的Lambda参数的Where方法,ORM Lite能正确识别实体null判断的意图,且编译器不会报错:
q = q.LeftJoin<PurchaseInvoice, PurchaseInvoiceProjectLink>((pi, pipl) => pi.Id == pipl.PurchaseInvoiceId); q = q.Where((PurchaseInvoice pi, PurchaseInvoiceProjectLink pipl) => Sql.In(pipl.ProjectId, UserSession.ProjectIds) || pipl == null);
这种写法下,ORM Lite会自动将pipl == null转换为关联表主键IS NULL的SQL,完全符合需求。
问题根源
原写法中,Where<PurchaseInvoiceProjectLink>(s => s == null)的s被编译器视为非null实体(单表Where的表达式参数默认被推断为非null),因此触发CS0472警告;同时ORM Lite解析时错误将实体null判断转换成了空字符串的null判断,导致逻辑失效。
内容的提问来源于stack exchange,提问作者marcinn
相关产品推荐
相关产品推荐

