Linq Orderby random ThreadSafe for use in ASP.NET

2020-01-26 07:30发布

i'm using Asp.net MVC with Sharp Architecture.

I have this code:

return _repositoryKeyWord.FindAll(x => x.Category.Id == idCAtegory)
                .Take(50).ToList();

How can i order by random? Note: i don't want to order the 50 extracted items, i want order before and then extract 50 items.

thks

5条回答
萌系小妹纸
2楼-- · 2020-01-26 07:49

One way to achieve efficiently is to add a column to your data Shuffle that is populated with a random int (as each record is created).

The query to access the table then becomes ...

Random random = new Random();
int seed = random.Next();
result = result.OrderBy(s => (~(s.Shuffle & seed)) & (s.Shuffle | seed)); // ^ seed);

This does an XOR operation in the database and orders by the results of that XOR.

Advantages:-

  1. Efficient: SQL handles the ordering, no need to fetch the whole table
  2. Repeatable: (good for testing) - can use the same random seed to generate the same random order
  3. Works on most (all?) Entity Framework supported databases

This is the approach used by my home automation system to randomize playlists. It picks a new seed each day giving a consistent order during the day (allowing easy pause / resume capabilities) but a fresh look at each playlist each new day.

查看更多
来,给爷笑一个
3楼-- · 2020-01-26 07:53

You can do this in T-Sql as described here. I don't think you can do it in linq without loading the whole result set into memory and then throwing most of it away, which you do not want to do.

查看更多
老娘就宠你
4楼-- · 2020-01-26 07:55

How about this?

return _repositoryKeyWord.FindAll(x => x.Category.Id == idCAtegory)
  .OrderBy (x => Guid.NewGuid())
  .Take(50).ToList();
查看更多
够拽才男人
5楼-- · 2020-01-26 08:00
Random random = new Random();
return _repositoryKeyWord.FindAll(x => x.Category.Id == idCAtegory)
                .OrderBy(x => r.Next())
                .Take(50).ToList();
查看更多
聊天终结者
6楼-- · 2020-01-26 08:01

Probably best to write your own extension method to do it.

public static class Extensions
{
    static readonly Random random = new Random();

    public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> items)
    {
        return Shuffle(items, random);
    }

    public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> items, Random random)
    {
        // Un-optimized algorithm taken from
        // http://en.wikipedia.org/wiki/Knuth_shuffle#The_modern_algorithm
        List<T> list = new List<T>(items);
        for (int i = list.Count - 1; i >= 1; i--) 
        {
            int j = random.Next(0, i);
            T temp = list[i];
            list[i] = list[j];
            list[j] = temp;
        }
        return list;
    }
}
查看更多
登录 后发表回答