当前位置:  开发笔记 > 编程语言 > 正文

Linq to Entities,随机顺序

如何解决《LinqtoEntities,随机顺序》经验,为你挑选了3个好方法。

如何以随机顺序返回匹配的实体?
要明确这是Entity Framework的东西和LINQ to Entities.

(航空代码)

IEnumerable results = from en in context.MyEntity
                                where en.type == myTypeVar
                                orderby ?????
                                select en;

谢谢

编辑:
我尝试将其添加到上下文中:

public Guid Random()
{
    return new Guid();
}

并使用此查询:

IEnumerable results = from en in context.MyEntity
                                where en.type == myTypeVar
                                orderby context.Random()
                                select en;

但我得到了这个错误:

System.NotSupportedException: LINQ to Entities does not recognize the method 'System.Guid Random()' method, and this method cannot be translated into a store expression..

编辑(当前代码):

IEnumerable results = (from en in context.MyEntity
                                 where en.type == myTypeVar
                                 orderby context.Random()
                                 select en).AsEnumerable();

Jon Skeet.. 50

这样做的一种简单方法是按顺序排序,Guid.NewGuid()然后在客户端进行排序.你可能能够说服EF在服务器端做一些随机的事情,但这并不一定简单 - 使用"随机数排序"这样做显然已被打破.

要在.NET端而不是在EF中进行排序,您需要AsEnumerable:

IEnumerable results = context.MyEntity
                                       .Where(en => en.type == myTypeVar)
                                       .AsEnumerable()
                                       .OrderBy(en => context.Random());

最好将无序版本放入列表然后随机播放.

Random rnd = ...; // Assume a suitable Random instance
List results = context.MyEntity
                                .Where(en => en.type == myTypeVar)
                                .ToList();

results.Shuffle(rnd); // Assuming an extension method on List

除了其他任何东西之外,洗牌比排序更有效.有关获取适当实例的详细信息,请参阅我的随机性文章Random.Stack Overflow上有很多Fisher-Yates shuffle实现.



1> Jon Skeet..:

这样做的一种简单方法是按顺序排序,Guid.NewGuid()然后在客户端进行排序.你可能能够说服EF在服务器端做一些随机的事情,但这并不一定简单 - 使用"随机数排序"这样做显然已被打破.

要在.NET端而不是在EF中进行排序,您需要AsEnumerable:

IEnumerable results = context.MyEntity
                                       .Where(en => en.type == myTypeVar)
                                       .AsEnumerable()
                                       .OrderBy(en => context.Random());

最好将无序版本放入列表然后随机播放.

Random rnd = ...; // Assume a suitable Random instance
List results = context.MyEntity
                                .Where(en => en.type == myTypeVar)
                                .ToList();

results.Shuffle(rnd); // Assuming an extension method on List

除了其他任何东西之外,洗牌比排序更有效.有关获取适当实例的详细信息,请参阅我的随机性文章Random.Stack Overflow上有很多Fisher-Yates shuffle实现.


卫生署.AsEnumerable.

2> Drew Noakes..:

Jon的回答是有帮助的,但实际上你可以让DB使用Guid和Linq to Entities 进行排序(至少,你可以在EF4中):

from e in MyEntities
orderby Guid.NewGuid()
select e

这会生成类似于的SQL:

SELECT
[Project1].[Id] AS [Id], 
[Project1].[Column1] AS [Column1]
FROM ( SELECT 
    NEWID() AS [C1],                     -- Guid created here
    [Extent1].[Id] AS [Id], 
    [Extent1].[Column1] AS [Column1],
    FROM [dbo].[MyEntities] AS [Extent1]
)  AS [Project1]
ORDER BY [Project1].[C1] ASC             -- Used for sorting here

在我的测试中,使用Take(10)生成的查询(转换为TOP 10SQL),查询在具有1,794,785行的表中始终在0.42和0.46秒之间运行.不知道SQL Server是否对此进行了任何类型的优化,或者是否为该表中的每一行生成了GUID .无论哪种方式,这将比将所有这些行放入我的进程并尝试在那里排序要快得多.



3> Michael Dama..:

简单的解决方案是创建一个数组(或a List),然后将其索引随机化.

编辑:

static IEnumerable Randomize(this IEnumerable source) {
  var array = source.ToArray();
  // randomize indexes (several approaches are possible)
  return array;
}

编辑:就个人而言,我发现Jon Skeet的答案更优雅:

var results = from ... in ... where ... orderby Guid.NewGuid() select ...

当然,你可以采用随机数发生器代替Guid.NewGuid().

推荐阅读
夏晶阳--艺术
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有