Entity Framework和MySQL如何实现随机排序

7

总结:我希望找到一种使用Entity Framework和MySQL(这很重要)生成随机顺序的方法。 这个解决方案不应该使用原始SQL查询或在从数据库加载所有值后排序。

我尝试过的:

我从那个答案中得到了使用NewGuid()生成随机顺序的想法。

代码:

var query = from e in context.Table
orderby Guid.NewGuid()
select e;
var test = query.FirstOrDefault();

始终抛出异常:

An error occurred while executing the command definition. See the inner exception for details.
Inner exception:
FUNCTION MyDatabase.NewGuid does not exist System.Exception {MySql.Data.MySqlClient.MySqlException}

看起来问题在于MySQL没有NewGuid()函数。

我该如何按照MySQL函数RAND()而不是NewGuid()进行排序呢?换句话说,如何在Entity Framework中使用自定义函数RAND?


@Tico,不,我没有Guid字段。我的PK是带有自增的整数。NewGuid()是一个函数,用于产生随机顺序(在这种情况下)。因此,每个查询结果都是不同的。我从这里https://dev59.com/7XRB5IYBdhLWcg3wV156#4120132中获得了关于NewGuid()的想法。 - Dador
从问题中的“编辑(当前代码)”来看,它似乎是有效的。 - trinaldi
请检查此链接(https://dev59.com/MnRB5IYBdhLWcg3wXWK2#648247),看是否有帮助。 - har07
@Dador,我明白你的问题。事实是:EF使用LINQ为您创建TSQL语句。NewGuid是C#函数,所以理论上它应该能够工作。请尝试这个:pastebin链接 - trinaldi
1
@Tico,它有效 :) 几乎是我当前用作解决方法的变体(不同之处在于我使用AsEnumerable()而不是ToList())。我之所以不经常使用这种方式的原因是将数据库中的所有行加载到客户端,而不是有限的行数(例如500行而不是10行)。无论如何,感谢您帮助调查此案例。 - Dador
显示剩余7条评论
4个回答

4
似乎问题在于MySQL没有NewGuid()函数。虽然我懒,但问题似乎是MySql没有名为NewGuid的函数。那么最简单的解决方案不是创建一个名为NewGuid的函数吗?
DELIMITER $$
CREATE DEFINER=`root`@`localhost` FUNCTION `NewGuid`() RETURNS char(36)
BEGIN
RETURN UUID();
END$$
DELIMITER ;

创建一个MySQL NewGuid功能后,我的问题得到了解决。
编辑:该问题说明“解决方案不应使用原始SQL查询”,但这并不需要原始SELECT / INSERT语句。但是确实需要创建数据库函数。
额外说明:我认为这在MySQL实现中技术上算是一个错误。Microsoft称它们的规范函数被所有数据提供程序支持。NewGuid列在其他规范函数下。

谢谢。有趣的解决方案。 - Dador
我使用了这个方法,它起作用了,但是在获取相关实体方面存在问题。因此,我首先获取了随机记录,然后创建了另一个查询来获取随机记录的相关实体。 - Sid

1
使用以下查询:
var query = from e in context.Table
            orderby SqlFunctions.Rand(1) 
            select e).Take(10);

希望你的MySql数据提供者无法被VS识别。

我知道Vs不直接支持MySQL到LINQ的转换。因此,您可以使用类似于以下内容的东西。

并且您可能需要下载这种类型的数据提供程序并尝试一下

下载并尝试它们:

  1. ALinq
  2. ORDesigner_VS2008ORDesigner_VS2010
  3. MySQL ADO.NET数据提供程序(如果已安装,则无需重新安装)。


如果您仍然失败,那么可以假设 Students 是来自学生表的模型。
using (ConsoleApplications.DataClasses1DataContext dd = new ConsoleApplications.DataClasses1DataContext())
{
   var result = (from stu in dd.Students.AsEnumerable()
      select new
      {
       stu.StudentName,
       RandomId = new Random(DateTime.Now.Millisecond).Next(dd.Students.Count())
      }).OrderBy(s => s.RandomId);

      foreach (var item in result)
      {
        Console.WriteLine(item.StudentName);
      }
}

1

我按照@Monkey Code给出的答案进行了操作,但有所不同的是,生成的GUID虽然是随机的,但是是有序的,对我来说快速解决的方法是使用以下代码:

...
RETURN MD5(UUID());
...

它基于以前的解决方案成功运作,但在获取相关实体方面存在问题。因此,我首先获取了随机记录,然后创建了另一个查询来获取随机记录的相关实体。 - Sid

-1

这可能对您有所帮助

var yourRecords = context.Table().OrderBy(c=>c.Name);

yourRecords = yourRecords.OrderBy(a => Guid.NewGuid());

请阅读问题。这个变体适用于MSSQL,但不适用于MySQL。 - Dador
1
将结果转换为列表,这样您就不再受数据库的限制。然后,按GUID排序将使用Linq2Objects。context.Table().ToList().OrderBy(x => Guid.NewGuid());只需确保限制记录集,以便不会将过多数据加载到内存中。 - Jaguir

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接