3

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

我希望我可以这样说:

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

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

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

NHibernate Insert into ... select ... 使用 GUID 作为 PrimaryKey

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

4

4 回答 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();

于 2013-07-25T23:20:36.397 回答
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 to 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()
于 2013-07-22T22:12:34.257 回答
0

我想这就是你要找的那个,

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

于 2013-07-24T04:04:35.133 回答
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;
于 2019-02-14T23:07:43.987 回答