Search code examples
c#ms-accessoledb

Random query returns same records each time


https://stackoverflow.com/a/9937425/159072

I am using the following query to select 5 random records from a table,

SELECT Top 5 *
FROM   (SELECT *,
           Rnd(ID) AS RandomValue
        FROM   Words)
ORDER  BY RandomValue 

This query works fine in MS Access.

But, the problem occurs when I use it in a c# application. It returns same 5 records on each occasion.

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Text;

namespace MicrosiftAccessDbProviderFactory______Test
{
    public class MyClass 
    {
        public int ID { get; set; }
        public string Name { get; set; }
    }

    public class Program
    {
        static void Main(string[] args)
        {
            string connString = @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=D:\db1.mdb;Persist Security Info=False";
            string providerName = @"System.Data.OleDb";
            DbProviderFactory factory = DbProviderFactories.GetFactory(providerName);

            IDbConnection Connection = factory.CreateConnection();
            Connection.ConnectionString = connString;
            Connection.Open();

            IDbTransaction Transaction = Connection.BeginTransaction();

            IDbCommand Command = factory.CreateCommand();
            Command.Connection = Connection;
            Command.Transaction = Transaction;

            int count = 5;

            Command.CommandText = @"SELECT Top " + count + @" ID, Name
                                    FROM   (SELECT *,
                                               Rnd(ID) AS RandomValue
                                            FROM   Words)
                                    ORDER  BY RandomValue";
            IDataReader dataReader = Command.ExecuteReader();
            IList<MyClass> list = null;
            MyClass item = null;
            while (dataReader.Read())
            {
                if (list == null)
                {
                    list = new List<MyClass>();
                }

                item = new MyClass();
                item.ID = dataReader.GetInt32(0);
                item.Name = dataReader.GetString(1);

                list.Add(item);
            }

            dataReader.Close();

            Transaction.Commit();

            string str = string.Empty;
        }
    }
}

How can I solve this issue?


Solution

  • You need to salt the Rnd function, like:

    SELECT * FROM SomeTable ORDER BY Rnd(-Timer()*[ID])
    

    Thus, in your query:

    Command.CommandText = @"SELECT Top " + count + @" ID, [Name]
                            FROM Words
                            ORDER BY Rnd(-Timer()*[ID])";