Всемогущий, Google, найди мне чего-нибудь!

воскресенье, 28 февраля 2010 г.

Рандомная выборка записей Linq To Sql

Сегодня столкнулся с проблемой рандомной выборки из базы данных, используя Linq To Sql. Например, ситуация такая: при переходе на страницу товара, вам также необходимо выгрузить несколько товаров из той же категории, но чтобы они выгружались рандомно (в произвольной последовательности).
При использовании T-SQL наш запрос должен выглядеть примерно так:
select * from products order by newid()
Итак, будем считать, что для уникального ключа в таблице товаров вы используете UniqueIdentifier (в C# это Guid), то при использовании наш запрос в Linq преобразуется в:
using (EcommerceDataContext dbContext = new EcommerceDataContext())
{
 var items = dbContext.Products.OrderBy(products => Guid.NewGuid());
}
Однако, вы увидите, что записи будут выгружаться только в той последовательности, в которой они были загружены. Для того, чтобы всё работало, необходимо связать функцию C# Guid.NewGuid() с функцией SQL newid(). Для этого необходимо следующее:
  1. щелкаем правой кнопкой по вашему dbml-файлу и переходим в режим кода;
  2. вы увидите примерно следующее:
    using System;
    using System.Data.Linq.Mapping;
    
    partial class EcommerceDataContext
    {
    }
    
  3. теперь необходимо вставить заветный код-связку:
    [Function(Name = "NEWID", IsComposable = true)]
    public Guid NewId()
    {
     return Guid.NewGuid();
    }
    
Атрибут Function принимает 2 параметра:
  • Name - название функции SQL Server;
  • IsComposable - true, если мы вызываем функцию (например, хранимые процедуры и пр.).
Теперь самое интересное. Сделаем запрос:
using (EcommerceDataContext dbContext = new EcommerceDataContext())
{
 var items = dbContext.Products.OrderBy(products => dbContext.NewId()).Take(5);
}
Число 5 в функции Take() означает, что необходимо взять 5 рандомных записей. Вуаля! Если что-то не работает - пишите. :)

3 комментария:

tayg комментирует...

Это грязный читинг!
Но за идею спасибо, хитрое решение! :)

Unknown комментирует...

Во-первых, не читинг, а идея! Во-вторых, не грязная, а нормальная, чтобы её использовать, САША! :)

Анонимный комментирует...

Спасибо, дружище! Помог!