我们有一个几年前编写的SQL
函数,它一直在导致零星的问题(我想已经有很多年了).
我终于弄到了一个客户数据库的备份,这样我就可以知道发生了什么.
该函数从数据库中提取最新的"会话"ID并返回它,除非@@ROWCOUNT
等于0
,在这种情况下,它返回一个空的string
.
ALTER FUNCTION [dbo].[GetCurrentSessionId]()
RETURNS nvarchar(255)
AS
BEGIN
declare @v nvarchar(255)
select top 1 @v = SessionId
from RestoreSession
where
SessionState <> 3 and -- Complete
SessionState <> 7 -- CompletedWithWarnings
order by SessionId desc
if @@ROWCOUNT = 0
set @v = ''
return @v
END
即使在数据库中有一个会话,这个函数每隔一次就会突然开始,总是返回空的string
.
当我在调试问题时第一次看到上面的函数时,我注意到了@@ROWCOUNT
,并认为它很奇怪.
我go 掉了@@ROWCOUNT
的条件,并重新测试了,这次是session ID was correctly returned.然后,我重新添加@@ROWCOUNT
条件并重新测试,它再次返回空string
.
可能重要也可能无关紧要的进一步细节.此函数是使用System.Data.SqlClient
命名空间中的实用程序从C#
应用程序调用的.
调用上述SQL
函数的方法如下所示.
public string GetCurrentSessionID()
{
string res = string.Empty;
using (var connection = _persistence.CreateSqlConnection())
{
var sessionsQuery = "select [dbo].GetCurrentSessionId() as SID";
using (var sqlCommand = connection.CreateCommand(sessionsQuery))
{
using (var sessionReader = sqlCommand.ExecuteReader())
{
if (sessionReader.Read())
{
if (!sessionReader.IsDBNull("SID"))
{
res = sessionReader.GetString("SID");
}
}
}
}
}
return res;
}
在上面的C#
个方法中,IsDBNull
和GetString
都是定制扩展方法,如下所示:
public static bool IsDBNull(this IDataRecord reader, string name)
{
return reader.IsDBNull(reader.GetOrdinal(name));
}
public static string GetString(this IDataRecord reader, string name)
{
return reader.GetString(reader.GetOrdinal(name));
}
我还想提一下,当我在SSMS中执行SQL
函数而不删除@@ROWCOUNT
条件语句时,会正确返回会话ID.
这似乎只有在从C#
应用程序调用函数时才会发生.
我认为修复方法是删除@@ROWCOUNT
条件语句,因为当我这样做时,C#
应用程序能够正确地提取会话ID.
我很好奇,在这种情况下,问题可能是什么?为什么当从C#
应用程序调用函数时,@@ROWCOUNT
似乎偶尔"不工作".