NHibernate - 使用LINQ选择随机记录数

时间:2013-07-22 19:44:36

标签: linq nhibernate random linq-to-nhibernate

有没有人知道如何使用LINQ在NHibernate中选择随机数量的记录。

我希望我可以这样说:

var rand = new Random();
var test = session.Query<Entity>().OrderBy(x => rand.Next()).Take(5).ToList();

然而,它不喜欢OrderBy表达式中的变量。一种选择是在我进行排序之前调用ToList,但这会抓取整个记录集,这不是理想的,因为它可以返回数千条记录。

我还发现了以下内容(向下滚动到底部答案):

NHibernate Insert into ... select ... with GUID as PrimaryKey

但是我不确定如何使用LINQ调用它。如果有人可以提供帮助,我会很感激。感谢

4 个答案:

答案 0 :(得分:4)

这个解决方案可能不是很好,因为它会改变你的实体的形状,但如果你的用例可以接受......

根据Ayende的这篇文章,看起来很容易将SQL函数映射到实体上的属性:

http://ayende.com/blog/1720/using-sql-functions-in-nhibernate

你可以添加像

这样的属性映射吗?

<property name='Random' formula='NEWID()'/>

您要定位的实体?然后你应该能够写一个像

这样的查询

var test = session.Query<Entity>().OrderBy(x => x.Random).Take(5).ToList();

答案 1 :(得分:1)

要使用NHibernate执行此操作,您需要添加以下类...

public class RandomOrder : Order
{
   public RandomOrder()
      : base(String.Empty, true)
   { }

   public override SqlString ToSqlString(ICriteria criteria, ICriteriaQuery criteriaQuery)
   {
      return new SqlString("NEWID()");
   }
}

以下扩展方法......

public static IQueryOver<TRoot, TSubType> OrderByRandom<TRoot, TSubType>(this IQueryOver<TRoot, TSubType> query)
{
   query.UnderlyingCriteria.AddOrder(new RandomOrder());

   return query;
}

这将允许您执行以下操作...

var test = session.QueryOver<Entity>().OrderByRandom().Take(5).ToList();


使用NHibernate FluentMapping和Linq到NHibernate执行此操作...

向您的班级添加新属性

public virtual string Random { get; set; }

然后将流动的地图添加到ClassMap<T>

Map(o => o.Random).Formula("NEWID()");

最后,您可以通过以下

来调用它

ctx.Query<T>().OrderBy(o => o.Random).Take(5).ToList();


要使用EF执行此操作,您需要将以下方法添加到DataContext类...

[Function(Name = "NEWID", IsComposable = true)]
[return: Parameter(DbType = "uniqueidentifier")]
public Guid Random()
{
   return Guid.NewGuid();
}

然后您可以通过执行以下操作来调用它...

dc.Products.OrderBy(o => dc.Random()).Take(5)

会给你以下结果......

SELECT TOP(5) * FROM Products ORDER BY NEWID()

答案 2 :(得分:0)

答案 3 :(得分:0)

实际上,有一种方法可以在LINQ IQueryable中调用自定义sql函数:

public Object register(Object args) {

       if(args.getClass().equals(java.util.Arrays.class)) {
            //do something
            // don't work
            return "";
       }
       if(args.getClass().equals(ArrayList.class)) {
            //do something
            // don't work
            return "";
       }
       //other Alt statement code
       return "";
}

然后,您必须创建称为Random2的自定义SQL函数。例如在PostgreSQL中将是:

internal static class CustomLinqExtensions
{
    [LinqExtensionMethod]
    public static string Random2(this int input)
    {
        // source: https://nhibernate.info/doc/nhibernate-reference/querylinq.html
        throw new NotImplementedException("This call should be translated to SQL and run db side, but it has run with .Net runtime");
    }
}

最后,您可以在OrderBy LINQ扩展中调用它

CREATE OR REPLACE FUNCTION RANDOM2(in INTEGER) RETURNS DOUBLE PRECISION AS
$$
BEGIN
  RETURN random();
END;
$$
  LANGUAGE plpgsql;

结果将生成以下sql查询:

var query = CurrentSession.Query<SampleClass>()
   .OrderBy(x => x.Id.Random2());