1

我在本机 SQL 中创建了一个复杂的搜索查询。基本上是这样的:

SELECT ID FROM t_Product WHERE Name LIKE @criteria
SELECT publisher, count(*) as number FROM t_Product GROUP BY publisher

它有 2SELECT条语句,我希望它在一次往返中发送到数据库服务器。

但我不知道如何在 Nhibernate 中实现这一点。

我考虑了以下选项,但似乎没有一个有效

  1. 使用CreateMultiQuery,但这只接受 HQL,不接受原生 SQL
  2. 使用CreateSQLQuery,但调用 List() 仅返回第一SELECT条语句的结果
  3. 迁移到存储过程不是一种选择,因为整个 SQL 是非常动态的。
  4. 我们仍然使用 Nhibernate 1.2,因此以后版本中的新功能也无法使用。

欢迎咨询。

4

4 回答 4

1

无法使用 NH 版本 1.2

Futures 是在 2.1 版中发布的,它允许您完全做到这一点。

例如

var blogs = s.CreateCriteria<Invoice>()
  .SetMaxResults(30)
  .Future<Invoice>();
var countOfInvoices = s.CreateCriteria<Invoice>()
  .SetProjection(Projections.Count(Projections.Id()))
  .FutureValue<int>();

因此,您要么升级,要么回退到 ADO.NET 并使用多个记录集,要么继续使用现有的!对不起!

于 2012-04-16T06:04:58.443 回答
1

这确实是特定于场景的,但是如果您坚持使用 NH 版本 1.2,并且您的目标是消除往返,您可以考虑使用子选择将其重写为单个查询。

类似于以下内容:

SELECT publisher, count(*) as number, 
(SELECT ID FROM t_Product WHERE Name LIKE @criteria) As theId 
FROM t_Product GROUP BY publisher

如果您的子查询仅返回一个值,则可以使用。

于 2012-04-16T17:31:05.083 回答
0

我不认为这是可能的,因为这两个查询都是 SELECT。

您可以在第一个查询之后尝试分号,并且它们之间有两个换行符,这对于某些数据库是必需的。我成功地运行了这样的查询脚本。如果它运行,请使用调试器查看返回的内容...

如果这不起作用,您需要单独的往返行程或切换到 HQL / Criteria。

于 2012-04-16T06:24:41.410 回答
0

您可以像这样使用 MultiQuery “Hack”:

程序:

CREATE PROCEDURE [dbo].[proc_Name]
AS BEGIN
    SELECT * FROM t_Question where ...
    SELECT * FROM t_Question where ........
END

NHibernate 查询代码:

public void ProcdureMultiTableQuery()
{
    var session = Session;
    var procSQLQuery = session.CreateSQLQuery("exec [proc_Name] ?,?");// prcodure returns two table
    procSQLQuery.SetParameter(0, userId);
    procSQLQuery.SetParameter(1, page);
    procSQLQuery.AddEntity(typeof(Question));

    var multiResults = session.CreateMultiQuery()
        .Add(procSQLQuery)
        // More table your procedure returns,more empty SQL query you should add
        .Add(session.CreateSQLQuery(" ").AddEntity(typeof(Question))) // the second table returns Question Model
        .List();
    if (multiResults == null || multiResults.Count == 0)
    {
        return;
    }
    if (multiResults.Count != 2)
    {
        return;
    }
    var questions1 = ConvertObjectsToArray<Question>((System.Collections.IList)multiResults[0]);
    var questions2 = ConvertObjectsToArray<Question>((System.Collections.IList)multiResults[1]);
}

static T[] ConvertObjectsToArray<T>(System.Collections.IList objects)
{
    if (objects == null || objects.Count == 0)
    {
        return null;
    }
    var array = new T[objects.Count];
    for (int i = 0; i < array.Length; i++)
    {
        array[i] = (T)objects[i];
    }
    return array;
}
于 2015-11-29T13:51:40.497 回答