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

问题描述 投票:3回答:4

有谁知道如何使用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调用它。如果有人可以提供帮助,我会很感激。谢谢

linq nhibernate random linq-to-nhibernate
4个回答
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
投票

要使用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()


0
投票

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

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");
    }
}

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

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

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

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

因此,将生成以下sql查询:

SELECT ... FROM Sample s order by Random2(s.Id) asc;
© www.soinside.com 2019 - 2024. All rights reserved.