【问题标题】:Multiple SELECT in NHibernate native SQLNHibernate 本机 SQL 中的多个 SELECT
【发布时间】:2023-03-03 10:33:01
【问题描述】:

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

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

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

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

我考虑过以下选项,但似乎没有一个可行

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

欢迎提出建议。

【问题讨论】:

  • 你为什么反对用 HQL 写它?

标签: c# sql nhibernate


【解决方案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 并使用多个记录集,要么接受现有的!对不起!

【讨论】:

  • 我使用 NH3.2 做了一些测试,看起来 Futures 也不支持原生 SQL。我想那是因为它是建立在 Multi query 之上的
  • HQL、QueryOver 和 ICriteria 都支持。老实说,从未尝试过使用原生 SQL
  • 作为旁注,您向我们展示的 SQL 示例可以非常简单地转换为 HQL,但我怀疑您的 SQL 更复杂!
【解决方案2】:

这确实是针对特定场景的,但如果您坚持使用 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

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

【讨论】:

  • 谢谢,你给了我另一种思路。如果我可以按照你的建议更改我的查询,让我试试。
  • 我应该提到的另一个警告是,您的“外部”查询将始终需要返回至少一行以供子选择查询返回结果,因此请确保您为此做好计划:)跨度>
【解决方案3】:

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

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

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

【讨论】:

  • 正如我所料:我认为它不起作用。使用 HQL/Criteria 或两次往返。
【解决方案4】:

您可以像这样使用 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;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-03-04
    • 1970-01-01
    • 2021-03-27
    • 2011-03-03
    • 1970-01-01
    • 2016-06-11
    • 1970-01-01
    相关资源
    最近更新 更多