EntityFramework6 / Npgsql:如何将orderBy nulls最后转换为SQL查询

时间:2018-02-19 18:51:46

标签: c# postgresql entity-framework-6 npgsql

我正在使用EntityFramework6.Npgsql并且正在使用包含数百万条记录的表。某些实体具有timestamp / DateTime列,允许null个值。用户通常需要对此列进行排序,并希望在nullasc排序中显示最后desc个值。该列对两种排序类型都有两个indizes,它们都设置为nulls last

我知道在SQL中我可以添加order by "DateColumn" desc nulls last并且postgres使用适当的索引并且查询返回(分页,例如25条记录)结果只有几毫秒。

然而,使用EntityFramework,为了最后使用nulls对降序进行排序,我必须添加如下内容:

entities.MyEntity
    .OrderByDescending(e => e.DateColumn.HasValue)
    .ThenByDescending(e => e.DateColumn)

然而,这转换为包含类似这样的排序的查询:

SELECT 
    CASE
        WHEN ("Extent1"."DateColumn" IS NOT NULL) THEN (TRUE)
        ELSE (FALSE)
    END AS "C1"

...

ORDER BY "C1", "DateColumn" DESC

哪个按预期工作,但查询需要几秒钟(而不是几毫秒)才能执行,因为它无法使用索引。

我尝试使用相同的表达式向列添加索引,但postgres在执行查询时似乎没有使用索引。

我可以在EntityFramework / Npgsql中编写一个可以转换为所需SQL(order by "DateColumn" desc nulls last)的查询?有没有办法拦截/覆盖Linq查询如何转换为SQL?

1 个答案:

答案 0 :(得分:0)

回答我自己的问题......

虽然仍然无法让Linq生成一个与nulls last一起排序的SQL查询,但我能够为postgres使用的null-check和date列本身创建一个组合索引:

CREATE INDEX "MyTable_IX_DateCombined"
  ON "MyTable"
  USING btree
  ((
  CASE
    WHEN "DateColumn" IS NOT NULL THEN true
    ELSE false
  END) DESC, "DateColumn" DESC);

由于我不得不在任何一种情况下创建一个额外的索引,我认为此解决方案在这一点上已经足够好了。