4

I'm trying to write a query which returns randomly ordered results. I've found this post Linq Orderby random ThreadSafe for use in ASP.NET which gave me some basic clue how to do that. But i'm getting following exception:

variable 'x' of type 'Accomodations.DAL.Model.Generated.Accomodation' referenced from scope '', but it is not defined

Here is my query:

                var query = session.QueryOver<Accomodation>()
                                   .OrderBy(x => (~(x.Id & seed)) & (x.Id | seed)).Asc; // this is the problematic line of code                    

                if (searchParams.District != 0)
                    query = query.Where(x => x.District.Id == searchParams.District);

                if (searchParams.Region != 0)
                    query = query.Where(x => x.Region.Id == searchParams.Region);

                if (searchParams.Location != 0)
                    query = query.Where(x => x.Location.Id == searchParams.Location);

                var futureCount = query.Clone().Select(Projections.RowCount()).FutureValue<int>();

                SearchAccomodationResultItem resultItemAlias = null;

                var futurePage = query                        
                    .SelectList(list => list
                        .Select(x => x.Id).WithAlias(() => resultItemAlias.Id)
                        .Select(x => x.AccomodationType.Id).WithAlias(() => resultItemAlias.AccomodationTypeId)
                        .Select(x => x.Region.Id).WithAlias(() => resultItemAlias.RegionId)
                        .Select(x => x.Name).WithAlias(() => resultItemAlias.Title)
                        .Select(x => x.MaxCapacity).WithAlias(() => resultItemAlias.MaxCapacity)
                        .Select(x => x.MinPrice).WithAlias(() => resultItemAlias.MinPrice)
                        .Select(x => x.MinStayLength).WithAlias(() => resultItemAlias.MinStayLength)
                        .Select(x => x.MainImageName).WithAlias(() => resultItemAlias.ImgSrc)                           
                        )                        
                    .TransformUsing(Transformers.AliasToBean<SearchAccomodationResultItem>())                        
                    .Skip(skip)                        
                    .Take(searchParams.PageSize)
                    .Future<SearchAccomodationResultItem>();

                searchResults = futurePage.ToList();
                numberOfResults = futureCount.Value;                    
            });

Any suggestion will be appreciated. Thanks

Community
  • 1
  • 1
Marian Ban
  • 8,158
  • 1
  • 32
  • 45

2 Answers2

2

Here is a good example of how to do this. This is a technique that I'm currently using.

http://puredotnetcoder.blogspot.com/2011/09/nhibernate-queryover-and-newid-or-rand.html

Edit

Below is taken from the above article and I've modified it slightly to include Skip as well.

public IList<CmsTestimonial> GetRandomTestimonials(int count, int skip) {  
  return Session  
    .QueryOver<CmsTestimonial>()  
    .OrderByRandom()
    .Take(count)  
    .Skip(skip)
    .List();  
} 
Cole W
  • 15,123
  • 6
  • 51
  • 85
  • Thanks, but I'm not sure if this helps me, because i want to persist the order while the users uses the pagination. Will the pagination work when i use your example? – Marian Ban May 19 '12 at 15:18
  • Why wouldn't pagination work? The `OrderByRandom` extension method defined in that posts returns `IQueryOver`. Did you see the example use at the end of the article? I've posted above if this is unclear. – Cole W May 19 '12 at 15:25
  • 1
    Good blog that, wonder who wrote it :) One point about pagination, this wont work as some of the records shown on page one could be shown on page 2 or 3 etc. To have random records for pagination is going to be very tricky as you would need to store ALL results in a table randomy (and maybe for every user)! I would really think why you need random records and paging! – Rippo May 19 '12 at 17:24
1

To use the above approach with paging, you could store the seed for the user (on a per session basis probably) and then use the RAND(seed) function in SQL - because you use the same seed, it will generate the same sequence of pseudo-random numbers and thus allow paging

Martin Ernst
  • 5,629
  • 2
  • 17
  • 14