【问题标题】:Calling a Stored Procedure from NHibernate and retrieving @@ROWCOUNT从 NHibernate 调用存储过程并检索 @@ROWCOUNT
【发布时间】:2016-04-05 12:37:40
【问题描述】:

在尝试解决这个问题几个小时后,我开始认为没有你的帮助我无法解决这个问题。情况:

我在 SQL Server Management Studio 中的存储过程(基本上):

SET NOCOUNT ON;
DELETE myTable
...                    -- Complex join query that deletes duplicates
RETURN @@ROWCOUNT      -- The number of rows affected

此过程运行良好,如果我在 SSMS 中运行它,则会运行以下查询:

USE myDb
GO
DECLARE @return_value int
EXEC    @return_value = [dbo].[StoredProcedure]
        @var1 = N'asd',
        @var2 = N'fgh',
        @var3 = N'jkl'
SELECT  'Return Value' = @return_value
GO

结果显示为 1 行,名称为 Return Value,值为 8700(这是正确,是查询删除的行数)。

我的问题始于我的 C#/NHibernate 代码。在我的 NHibernate 映射中:

<sql-query name="MyStoredProcedureName">
  exec dbo.StoredProcedure @var1=:var1, @var2=:var2, @var3=:var3
</sql-query>

在我调用存储过程的方法中:

var deletedEntities = session.GetNamedQuery("MyStoredProcedureName")
                             .SetString("var1", "asd")
                             .SetString("var2", "fgh")
                             .SetString("var3", "jkl")
                             .ExecuteUpdate();

这导致deletedEntities = -1。我希望它是deletedEntities = 8700

我想指出,以下确实返回了受影响的行数:

var deletedEntities = session.CreateQuery("DELETE Class c WHERE c.var1 = :var1 AND c.var2 = :var2 AND c.var3 = :var3")
                             .SetString("var1", var1)
                             .SetString("var2", var2)
                             .SetString("var3", var3)
                             .ExecuteUpdate();

其中Class 是属于NHibernate 映射的类。

所以,总结一下:

  1. 在 SIMPLE session.CreateQuery 上执行更新会返回受影响的行数 (GOOD)
  2. 在 COMPLEX session.GetNamedQuery 上执行更新返回 -1(错误)
  3. 当我在 SSMS 中执行此相同的复杂存储过程时,它会返回所需的 8700(好)

有人知道如何修复 2 吗?

【问题讨论】:

  • 您的问题与这些问题非常相似,但对于 实体框架 中的所有情况,它们都会返回 -1,请在此处查看它们:stackoverflow.com/questions/32140774/… 此处:@987654322 @
  • 谢谢您,现在就阅读。
  • @S.Akbari 我对他们创建的第一个变量 (db) 以及他们如何调用存储过程感到有些困惑。它与我在 NHibernate 中的称呼完全不同。此外,我看不到如何“将存储过程作为函数导入。右键单击实体模型的工作区,然后选择添加 -> 函数导入。” (这一定是最愚蠢的问题之一,但我的实体模型的工作区是什么?:S)。
  • 按照第二个链接中的建议更改存储过程怎么样?
  • 使用您提供的两个链接中的单词,我用谷歌搜索了更多内容,发现:csharptechies.blogspot.co.uk/2013/04/… 这实际上似乎有效。我将研究结合GetNamedQuery(映射).ExecuteUpdate() 组合而不是CreateSQLQuery.UniqueResult 组合的解决方案。

标签: c# sql-server stored-procedures nhibernate


【解决方案1】:

使用http://csharptechies.blogspot.co.uk/2013/04/how-to-get-return-value-from-stored.html 我的代码可以正常工作。在过程中,将RETURN @@ROWCOUNT替换为SELECT @@ROWCOUNT

在 C# 代码中,我将 .ExecuteUpdate() 替换为 .UniqueResult()。 UniqueResult 返回一个对象,其中将包含@@ROWCOUNT 值(需要按照上面链接中的说明转换为 int)。

所以解决方案是组合(我想使用映射):

  1. 使用SELECT 而不是RETURN
  2. 使用 .UniqueResult() 代替 .ExecuteUpdate()

编辑:我遇到了另一个问题,只要有大量记录要删除,查询就会超时。我在其他问题的帮助下解决了这个问题,例如SQL Server: Effects of using 'WITH RECOMPILE' in proc definition?

  1. 在大型表的复杂查询中使用WITH RECOMPILE(我的查询涉及left outer joinmin(id)group by,受影响的记录数通常在20.000 左右,但最多可运行100.000 + 并且我的表中有超过 350.000.000 条记录)以避免超时。

【讨论】:

  • 我已经这样做了 :) 我现在收到了一个我昨天没有收到的错误,所以它可能仍然无法正常工作:(我会尽快回复它。
  • 我觉得查询有效,因为我使用了不存在的数据。如果我使用 Var1、Var2 和 Var3 并将它们设置为 value_does_not_exist,则执行查询。一旦它找到数据,它就会给我一个错误说could not execute query ... [SQL: exec StoredProcedureName @p0, @p1, @p2] edit:当我使用不在数据库中的值时它不会给出这个错误。很奇怪?它与返回值/删除权限或其他什么有关吗? :S
  • 不确定到底发生了什么,但正如您猜想的那样,我认为这可能是返回值问题。我不知道 NHibernate 但 EF 不支持开箱即用的存储过程返回标量值。
  • @S.Akbari 我发现了问题所在,但不知道如何解决:当有 3 个重复值时它起作用(它会立即删除其中的 2 个)。但是,当有 78297 条记录要删除时,查询会超时。结论:我的查询很糟糕,我应该感觉很糟糕。 但是当我从 SSMS 运行存储过程时,删除 78297 条记录需要 4 秒。所以问题是,当我从 Visual Studio(我的 Web 服务)运行查询时,为什么查询需要超过 30 秒(和超时)。
  • 我建议你在 EF 中也这样做并比较结果。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多