微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用没有OrderBy和filter的First / FirstOrDefault / Last / LastOrDefault操作可能会导致不可预测的结果

如何解决使用没有OrderBy和filter的First / FirstOrDefault / Last / LastOrDefault操作可能会导致不可预测的结果

我有一个linq查询,它给了我警告,但仍然有效。我想摆脱警告。

uses First/FirstOrDefault/Last/LastOrDefault operation without OrderBy and filter which may lead to unpredictable results.

linq查询

var list = (from u in _db.user
        join r in _db.resource on u.userId equals r.userId
        join t in _db.team on u.bossId equals t.bossId
        where r.pid == pid
        select new MyDto
        {
            pid = pid,userId = u.userId,teamId = t.teamId,name = t.name
        }).GroupBy(d => d.userId).Select(x => x.First()).OrderBy(y => y.userId).ToList();

我使用EntityFramework Core 2.1

更新:

我通过注释更改了代码

var list = (from u in _db.user
        join r in _db.resource on u.userId equals r.userId
        join t in _db.team on u.bossId equals t.bossId
        where r.pid == pid
        select new MyDto
        {
            pid = pid,name = t.name
        })
        .GroupBy(d => d.userId)
        .Select(x => x.OrderBy(y => y.userId)
        .First())
        .ToList();

然后有一个不同的警告。

LINQ表达式'GroupBy([user] .userId,new MyDto(){pid = Convert(_8_locals1_pid_2,Int16),userId = [user] .UserId,.....)可以 不翻译,将在本地进行评估。

解决方法

我们有这个表情

.Select(x => x.First())

哪个记录将是该表达式的第一记录?无法知道,因为此时OrderBy()子句尚未处理。 每次对相同数据运行相同查询时,您可能会获得不同的结果,具体取决于从数据库返回记录的顺序。结果是无法预测的,就像错误消息中所说的一样。

但是确定数据库每次都将以相同的顺序返回它们吗? ,您不能假设那样。除非查询中包含ORDER BY子句,否则SQL查询中结果的顺序为未定义。大多数时候,您会获得主键排序(不必与插入顺序匹配!),但是有很多事情可以改变这种情况:匹配不同的索引,将JOIN匹配到表具有不同顺序或不同索引,在同一表上与另一个查询并行执行+循环索引遍历,等等。

要解决此问题,您必须先致电OrderBy(),然后再致电。。

再深入一点,这甚至不是SQL的一部分。这项工作正在您的客户上进行。这不好,因为表上的任何索引都不再可用。应该可以在数据库服务器上完成所有这些工作,但是选择组的第一条记录可能意味着您需要横向连接/ APPLY或row_number()窗口化功能,而这些功能很难用EF复制。要完全删除所有警告,您可能必须编写原始SQL语句:

First()

环顾四周,可以在is possible中使用EF中的row_number(),但是在这一点上,我个人觉得使用SQL更容易。我认为ORM对于这些更复杂的查询没有帮助,因为您仍然必须了解所需的SQL,并且还必须了解ORM的复杂性才能构建它。换句话说,原本可以使您的工作更轻松的工具反而使工作变得更加困难。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。