如何以随机顺序返回匹配的实体?
要明确这是Entity Framework的东西和LINQ to Entities.
(航空代码)
IEnumerableresults = from en in context.MyEntity where en.type == myTypeVar orderby ????? select en;
谢谢
编辑:
我尝试将其添加到上下文中:
public Guid Random() { return new Guid(); }
并使用此查询:
IEnumerableresults = 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..
编辑(当前代码):
IEnumerableresults = (from en in context.MyEntity where en.type == myTypeVar orderby context.Random() select en).AsEnumerable();
Jon Skeet.. 50
这样做的一种简单方法是按顺序排序,Guid.NewGuid()
然后在客户端进行排序.你可能能够说服EF在服务器端做一些随机的事情,但这并不一定简单 - 使用"随机数排序"这样做显然已被打破.
要在.NET端而不是在EF中进行排序,您需要AsEnumerable
:
IEnumerableresults = context.MyEntity .Where(en => en.type == myTypeVar) .AsEnumerable() .OrderBy(en => context.Random());
最好将无序版本放入列表然后随机播放.
Random rnd = ...; // Assume a suitable Random instance Listresults = context.MyEntity .Where(en => en.type == myTypeVar) .ToList(); results.Shuffle(rnd); // Assuming an extension method on List
除了其他任何东西之外,洗牌比排序更有效.有关获取适当实例的详细信息,请参阅我的随机性文章Random
.Stack Overflow上有很多Fisher-Yates shuffle实现.
这样做的一种简单方法是按顺序排序,Guid.NewGuid()
然后在客户端进行排序.你可能能够说服EF在服务器端做一些随机的事情,但这并不一定简单 - 使用"随机数排序"这样做显然已被打破.
要在.NET端而不是在EF中进行排序,您需要AsEnumerable
:
IEnumerableresults = context.MyEntity .Where(en => en.type == myTypeVar) .AsEnumerable() .OrderBy(en => context.Random());
最好将无序版本放入列表然后随机播放.
Random rnd = ...; // Assume a suitable Random instance Listresults = context.MyEntity .Where(en => en.type == myTypeVar) .ToList(); results.Shuffle(rnd); // Assuming an extension method on List
除了其他任何东西之外,洗牌比排序更有效.有关获取适当实例的详细信息,请参阅我的随机性文章Random
.Stack Overflow上有很多Fisher-Yates shuffle实现.
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 10
SQL),查询在具有1,794,785行的表中始终在0.42和0.46秒之间运行.不知道SQL Server是否对此进行了任何类型的优化,或者是否为该表中的每一行生成了GUID .无论哪种方式,这将比将所有这些行放入我的进程并尝试在那里排序要快得多.
简单的解决方案是创建一个数组(或a List
),然后将其索引随机化.
编辑:
static IEnumerableRandomize (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()
.