7

Summary: I want to find a way to make random order with Entity Framework and MySQL (that's important). That solution shouldn't use raw sql queries or ordering AFTER loading all values from database.

What I've tried:

I took idea about using NewGuid() for random order from that answer.

Code:

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

Always thrown exception:

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}

Seems that problem is that MySQL doesn't have function NewGuid().

How can I order by MySQL function RAND() instead of NewGuid(). In other words, how to use custom function RAND in Entity Framework?

Community
  • 1
  • 1
Dador
  • 5,277
  • 1
  • 19
  • 23
  • You have an Entity with a `Guid` as its PK and is trying to order by creating new `Guid`s? If that's the case, you should `order by e.NameOfYourId`. – trinaldi Dec 21 '13 at 03:19
  • @Tico, no, I don't have Guid field. My PK is integer with autoincrement. NewGuid() is function used (in that case) for random order. So every query result is diffrent. I took idea about NewGuid() from here http://stackoverflow.com/a/4120132/596207 – Dador Dec 21 '13 at 03:27
  • The static method `Guid.NewGuid()` creates a new valid `Guid`, so you're basically ordering your query in a condition that does not "works". I think that is better to List all your elements and then randomize them. – trinaldi Dec 21 '13 at 03:29
  • Che the **Edit (Current code):** from the question, it seems to be working. – trinaldi Dec 21 '13 at 03:35
  • check if [this](http://stackoverflow.com/a/648247/2998271) can help.. – har07 Dec 21 '13 at 03:39
  • @Tico you used MySQL or MSSQL? If MySQL, can you say your version of server and version of Connector/Net? – Dador Dec 21 '13 at 03:41
  • @har07 thanks. Code in that answer using class `Function`. There is such class in linq-to-sql, but not in Entity Framework. Don't you know, maybe there are exists an analog for `Function`? – Dador Dec 21 '13 at 03:46
  • I use MSSQL, @Dador. I don't see a problem getting the data and them randomize it. Did you try the answers to the question you've posted? – trinaldi Dec 21 '13 at 03:49
  • @Tico, yes, of course. This works on MSSQL cause it has function [NewGuid](http://msdn.microsoft.com/en-us/library/system.guid.newguid(v=vs.110).aspx), but MySQL doesn't have function `NewGuid`. Thought it have functions named [Uuid](http://dev.mysql.com/doc/refman/5.1/en/mathematical-functions.html#function_rand) and [Rand](http://dev.mysql.com/doc/refman/5.1/en/mathematical-functions.html#function_rand). The question is how to use these functions in Entity Framework. – Dador Dec 21 '13 at 03:57
  • @Dador, I understood your question. The thing is: EF uses LINQ to create the TSQL for you. NewGuid is C# function, so - in theory - it should work. Try this: [pastebin link](http://pastebin.com/sjusv8Ma) – trinaldi Dec 21 '13 at 04:04
  • 1
    @Tico, it works :) Almost that variant I'm currently use as workaround (difference that I'm using `AsEnumerable()` instead of `ToList()`). The reason why I'm not use such variant constantly is that all rows from database loading to client instead of limited rows (for example 500 rows instead of 10). Anyway, thanks you for help with investigating this case. – Dador Dec 21 '13 at 04:16
  • My current project depends entirely on EF :) Glad to help! – trinaldi Dec 21 '13 at 04:18

4 Answers4

4

Seems that problem is that MySQL doesn't have function NewGuid().

Call me lazy, but the problem seems to be that MySql does not have a function called NewGuid. So wouldn't the easiest solution be to create a function in MySql called NewGuid?

DELIMITER $$
CREATE DEFINER=`root`@`localhost` FUNCTION `NewGuid`() RETURNS char(36)
BEGIN
RETURN UUID();
END$$
DELIMITER ;

Problem is solved for me after creating a MySQL NewGuid function.

Edit: The Questions states "solution shouldn't use raw sql queries" and this does not require a raw SELECT/INSERT statement. It does require the database function to be created though.

Extra note: I would say that this is technically a bug in the MySQL implementation. Canonical Functions are said to be "supported by all data providers" by Microsoft. NewGuid is listed under Other Canonical Functions

Monkey Code
  • 592
  • 6
  • 20
  • I used this, and it worked, but there was problem with getting related entity with this. So i first get the random records, and then created another query to get related entity for random records. – Sid Jun 30 '19 at 08:06
1

Use the below query:

var query = from e in context.Table
            orderby SqlFunctions.Rand(1) 
            select e).Take(10);

And hope your MySql Data Providor cannot be recognized by VS.

I know that Vs doesn't support MySQL to LINQ directly.. So maybe you can use something like.

And perhpas you need to download this kind of data providor and have a try

download them and have a try:

  1. ALinq.
  2. ORDesigner_VS2008 or ORDesigner_VS2010.
  3. MySQL ADO.NET Data Provider (If installed, no need to reinstall).


And If you still fail, this can be right Suppose Students is a model from Student table

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);
      }
}
Code Lღver
  • 15,573
  • 16
  • 56
  • 75
1

I followed the answer given by @Monkey Code but with a difference, the guid generated, despite random, was ordered and the quick solution for me was to use the following:

...
RETURN MD5(UUID());
...
jcsmata
  • 68
  • 1
  • 6
  • It worked as it based on previous solution, but there was problem with getting related entity with this. So i first get the random records, and then created another query to get related entity for random records. – Sid Jun 30 '19 at 08:08
-1

This may help you

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

yourRecords = yourRecords.OrderBy(a => Guid.NewGuid());
Code Lღver
  • 15,573
  • 16
  • 56
  • 75
Alps
  • 37
  • 1
  • 1
  • 7
  • Please read the question. This variant works with MSSQL, but didn't works with MySQL. – Dador Dec 28 '13 at 11:36
  • 1
    Convert the results to a list so that you are no longer tied to the database. Then the order by guid will use linq2objects. `context.Table().ToList().OrderBy(x => Guid.NewGuid());` Just make sure you limit the record set so you don't load too much data into memmory. – Jaguir Dec 30 '13 at 15:49