模拟实体框架的 .使用 SQL Server 时的 Last()



SQL服务器能够使用其函数TOP(1)来翻译EF.First()。但是,使用实体框架的.Last()函数时,它会引发异常。出于显而易见的原因,SQL 服务器无法识别此类功能。

我曾经通过降序排序并取第一行来解决这个问题:

var v = db.Table.OrderByDescending(t => t.ID).FirstOrDefault(t => t.ClientNumber == ClientNumberDetected);

这通过单个查询来完成,但在查询之前对整个表(百万行)进行排序......

如果我滥用这种技术,我有充分的理由认为会有速度问题吗?

我想到了类似的东西...但它需要两个查询:

int maxID_of_Client = db.Where(t => t.ClientNumber == ClientNumberDetected).Max(t => t.ID);
var v = db.First(t => t.ID == maxID_of_Client);

它包括检索客户端的最大 ID,然后使用此 ID 检索客户端的最后一行。

查询两次似乎并不快...

必须有一种方法可以对此进行优化,并使用单个查询而不对数百万个数据进行排序。

除非有什么我不明白的地方,否则我可能不是第一个想到这个问题的人,我想永远解决它!

提前谢谢。

驱动此问题的假设是,没有排序子句的结果集以任何可预测的顺序从数据库返回。

实际上,从 SQL 返回的结果集没有隐式排序,也不应假定任何隐式排序。

因此,结果

db.Table.FirstOrDefault(t => t.ClientNumber == ClientNumberDetected)

实际上是不确定的。

无论你是拿第一个还是最后一个,不点菜都是没有意义的。

现在,在 SQL 中,您将排序子句添加到 LINQ 中,转到什么?它将类似于...

SELECT TOP(1) something FROM somewhere WHERE foo=bar ORDER BY somevalue

或者,在降序/最后一种情况下

SELECT TOP(1) something FROM somewhere WHERE foo=bar ORDER BY somevalue DESC

从SQL的POV来看,这里没有显着差异,您的数据库将针对此类查询进行优化。索引可以在任一方向上扫描,并且上面每个查询的成本是相同的。

TL;DR

db.Table.OrderByDescending(t => t.ID)
.FirstOrDefault(t => t.ClientNumber == ClientNumberDetected)

就好了。

最新更新