此问题已在此处有答案:
EF Code First: How to get random rows(4个答案)
Randomize a List(30个答案)
7天前关闭
如何在ABP框架中复制此SQL查询的行为?SQL查询是:
SELECT * FROM App_Profile
ORDER BY NEWID()
我尝试使用以下LINQ表达式,但它不起作用-我想每次都获得随机记录,但我总是得到相同的结果:
query.Skip(input.SkipCount).Take(input.MaxResultCount).OrderBy(x => Guid.NewGuid());
var profiles= await _asyncExecuter.ToListAsync(query);
- 具体例子:我有一个包含100个问题的数据集,一个返回30个问题的端点,每个问题都有一个潜在答案的集合。我的目标是确保每次用户调用端点时,它都返回一组不同的问题及其潜在的响应,而不管第一个和第二个结果中是否碰巧存在任何问题。
P.S:我使用ABP框架,EF Core 6
- 在尝试之后,我得到了这个解决方案,似乎问题在于
await _asyncExecuter.ToListAsync(query)
,我不知道为什么。我试过使用var questions = query.OrderBy(x => Guid.NewGuid()).Take(input.MaxResultCount).ToList();
。
3条答案
按热度按时间gv8xihay1#
Tatranskymedved已经回答了你的问题,但要扩展你似乎感到困惑的元素:
使用以下命令只将选定的项目加载到内存中,而不是先将所有内容加载到内存中:
现在真实的的问题是你到底想干什么随机地对整个行集合进行排序,然后使用skip和take作为DB查询没有任何意义。当然,这将从随机集合中获取一页数据,但如果您的目标是加载已随机化的数据页,则这可能不会像您期望的那样工作,因为每个查询都会重新随机化集合,因此您可以,并且将在多个分页调用中返回相同的项。需要在分页调用之间保持排序。如果你只想从整个集合中随机选取100个项目,你不需要
Skip
,只需要使用Take
来获得前100个随机项目。我不知道_asyncExecutor是什么,但我很确定它不是必需的,除非它是一个记录输出或类似的 Package 器,但我怀疑它是为了做一些像 Package 一个同步操作被视为异步操作。(不需要,因为EF支持异步操作)
为了解释你所看到的例子:
如果Skip值为100,MaxResultCount为10,则这将始终取行101-110,然后随机排序这10个结果,而不是随机排序整个集合。这种方法的另一个问题是,数据将被读入的假设默认顺序是不可靠的,并且将随着数据从集合中添加/移除而变化。一开始,它看起来像默认顺序是ID或添加行的顺序,但随着集合的增长和变化,这将不再可靠。
具体例子:我有一个包含100个问题的数据集和一个返回30个问题的端点。我想做的是确保每次用户调用端点时,它都将返回一组不同的问题,而不管第一个和第二个结果中是否碰巧存在任何问题。
如果您想从100个问题的数据集中选择30个随机问题,并且您不关心问题是否可以在呼叫之间重复:
这就是你所需要的。
如果要确保接下来的30个问题不包括用户已经尝试过的问题,则确保这一点的最佳方法是缓存您已经选择的问题ID,并将其从集合中排除:
初始状态:
这假设是一个web应用程序,但是如果是一个应用程序,questionIdsAsked可以只是一个私有成员,如果需要可以清除。这将检查当前用户是否被提供了一组问题。在会话的第一次运行时,我们从数据库中获取前30个问题,并将这些问题ID记录到会话状态中。这样,当我们再次调用它时,我们从上一次运行中获得30个问题ID,并在重新随机化并获取30个新问题之前从查询中排除这些问题。显然,如果您采用这种方法,您将需要处理可能会用完问题或足以获得完整的30个问题的场景。
编辑:请注意,如果您急于加载响应或其他数据,则不能将
AsSplitQuery
与此方法一起使用。这将导致对正在阅读的问题的随机响应集,因此一些问题可能会加载其答案,而其他问题则不会。使用Split Queries,EF会生成两个查询,看起来像这样:第一个查询将获取10个随机问题,但是为了使拆分查询可靠地工作,排序必须相同,在本例中并非如此。它将加载不同的10个随机问题的响应。
您需要接受问题及其回答的笛卡尔积的成本,或者可以考虑手动执行拆分查询:
更好的方法是将问题和所需的响应细节投影到DTO中,以尽可能减少查询笛卡尔,这样就不必求助于
Include
和AsSplitQuery
。91zkwejq2#
这样做的问题是,您首先选择项目(总是相同的集合),然后随机排序。
更改Linq调用的顺序,并在开始获取元素之前调用
OrderBy()
:6rqinv9w3#
我无法重现这个问题(也就是说,我从数据库中获得结果)。我使用EF Core 7和SQL Server。具体来说,我有以下代码:
我看到生成了以下查询:
我从数据库中随机得到两行。但是,由于行是随机的,我不确定
Skip()
的必要性