Linq查询中获得随机排序的几种方法

2011-04-22

在进行程序开发的时候经常会要获取数据库中指定条的随机数据,就如我现在做的在线考试系统,需要随机选取题目组成试卷,如果使用ado.net开发的话,可以直接使用sql查询的order by newId()就可以使数据随机排序,然后获取前n条数据即可。但是如果使用Linq来开发的话,就没有这么方便了,因为Linq没有像sql那样对随机排序有原生的支持,可是我们需要解决这个问题,下面就介绍我找到的两个方法。

第一种是通过视图来解决的,sql中既然支持newid(),我们就可以把这个封装到数据库中,然后再通过Linq来调用,而这个东西就是数据库的视图。具体操作如下:

第一步:创建视图,代码为

create view View_QuestionRandom as select q.*,newid() as r from Questions as q

第二步:将该视图托到项目的dbml文件中 第三步:使用Linq查询,代码示例

context.View_QuestionRandom.OrderBy(n => n.r).Take(10)

这里使用OrderBy(n => n.r)时其实就相当于sql查询时的order by newId(),这个方法很巧妙,但是会使查询出来的数据有冗余(r)。

第二种方法是通过向dbml中添加newId()方法来实现的,具体操作如下:

第一步:在dbml项下自动生成的*. designer.cs中添加我们需要的方法NEWID(),添加代码及位置如下:

private static System.Data.Linq.Mapping.MappingSource mappingSource = new AttributeMappingSource();
//在自动生成的mapping code中添加
[Function(Name = "NEWID", IsComposable = true)]
public Guid NEWID()
{
    return ((Guid)(this.ExecuteMethodCall(this, ((MethodInfo)(MethodInfo.GetCurrentMethod()))).ReturnValue));
}

第二步:使用Linq查询,代码示例

context.Questions.Where(n => n.IsApproved).OrderBy(n => db.NEWID()).Take(10);

第二种方法虽然好,但是由于每次重新托dbml都会重新生成*. designer.cs文件,所以每次都要重新往里面添加NEWID()方法,这样很不方便(对于刚开始数据库没有设计得很好的)。

以上就是我要介绍的两种方法,这两种方法都是来自网上其他牛人,我只不过是做搬运工和测试而已。网上还有一个方法是使用Guid.NewGuid()来获得随机,但是经过我实验这个方法对于数据库查询无法实现(或许是我的方法不对吧),但是对于数组或List等就可以进行随机排序,代码示例:

int[] array = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
var result = array.OrderBy(n => Guid.NewGuid());

这样的话基本就解决问题了,如果大家还有什么好方法,欢迎留言告知,谢谢!