MSSQL 存储过程未正确读取参数
MSSQL Stored Procedure not reading parameter correctly
我是 learning/building AWS RDS/Lambda/API 网关的 API。数据库是 MSSQL,因为我们过去一直使用 SQL 数据库,而 Lambda 是在 Visual Studio.
中用 C# 编写的(我也是 C# 的新手)
我已经用一个简单的虚拟用户 table 设置了一个测试数据库,并编写了一个基本的 SP 来获取数据。 SP 采用单个可选参数 'User' 和 returns 找到该用户的所有列,如果没有发出参数则为所有列。
在 MSSMS 中进行了测试,SP 在有参数和无参数的情况下都能正常工作。我已经在 Visual Studio 中编写了函数,并使用 Mock Lambda 测试工具进行了测试。如果没有发送参数,那么我会得到一个完整的用户列表。但是,当我尝试传递参数时,reader 执行但 returns 没有结果。我已经检查并三次检查了参数名称和值,两者都应该有效。我不明白为什么会这样?我已经在 VB.net 中这样做了数千次,从来没有遇到过问题。
代码如下:
SP:
USE [playground]
GO
/****** Object: StoredProcedure [dbo].[GetUsers] Script Date: 22/02/2021 14:29:09 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: <Author,,Name>
-- Create date: <Create Date,,>
-- Description: <Description,,>
-- =============================================
ALTER PROCEDURE [dbo].[GetUsers]
@User varchar(60) = null
AS
BEGIN
SELECT *
FROM PlayUsers
WHERE (@User IS NULL OR UName = @User)
END
C#代码:
public static class Function
{
/// <summary>
/// Run a simple SP with optinal parameter to prove concept
/// </summary>
public static object FunctionHandler(ILambdaContext context)
{
var users = "";
Console.WriteLine("*** Starting function ***");
try
{
using (SqlConnection conn = new SqlConnection(GetConnectionString()))
{
SqlCommand cmd = new SqlCommand("GetUsers", conn)
{
CommandType = CommandType.StoredProcedure
};
cmd.Parameters.AddWithValue("@User", "BearDown");
//cmd.Parameters.Add("@User", SqlDbType.VarChar).Value = "BearDown";
conn.Open();
using (SqlDataReader rdr = cmd.ExecuteReader())
{
while (rdr.Read())
{
users += ToJson(rdr);
}
}
conn.Close();
cmd.Dispose();
conn.Dispose();
}
}
catch (Exception ex)
{
Console.WriteLine($"Exception thrown: {ex}");
}
finally
{
Console.WriteLine("*** End function ***");
}
return users;
}
public static string ToJson(this SqlDataReader rdr)
{
StringBuilder sb = new StringBuilder();
StringWriter sw = new StringWriter(sb);
using (JsonWriter jsonWriter = new JsonTextWriter(sw))
{
jsonWriter.WriteStartArray();
while (rdr.Read())
{
jsonWriter.WriteStartObject();
int fields = rdr.FieldCount;
for (int i = 0; i < fields; i++)
{
jsonWriter.WritePropertyName(rdr.GetName(i));
jsonWriter.WriteValue(rdr[i]);
}
jsonWriter.WriteEndObject();
}
jsonWriter.WriteEndArray();
return sw.ToString();
}
}
}
如您所见,我尝试了 .Add 和 .AddWithValue 来添加参数,但似乎都没有传递参数。我已经逐步检查了代码,可以看到它通过 SQL Reader 执行 运行 并且没有异常命中,但它从未找到任何结果。
将监视添加到 rdr 它显示:使用参数时“枚举未产生任何结果”。但同样,在 MSSMS 中执行 SP 时,这两个值都可以正常工作。
** 更新 **
在解决这个问题之后,我发现替换
using (SqlDataReader rdr = cmd.ExecuteReader())
{
while (rdr.Read())
{
users = rdr.ToJson();
}
}
只有
using (SqlDataReader rdr = cmd.ExecuteReader())
{
users = rdr.ToJson();
}
按要求工作。我想我会把它包装在一个 if (rdr.HasRows) 中,看起来像是一个解决方案。
您在 FunctionHandler
中调用 rdr.Read()
(“将 reader 推进到下一条记录”),然后在您从那里调用的 ToJson
函数中再次调用...我不认为这是预期的行为?你总是在那里跳过一条记录......我的建议是尝试在 FunctionHandler
.
中不使用 rer.Read()
我是 learning/building AWS RDS/Lambda/API 网关的 API。数据库是 MSSQL,因为我们过去一直使用 SQL 数据库,而 Lambda 是在 Visual Studio.
中用 C# 编写的(我也是 C# 的新手)我已经用一个简单的虚拟用户 table 设置了一个测试数据库,并编写了一个基本的 SP 来获取数据。 SP 采用单个可选参数 'User' 和 returns 找到该用户的所有列,如果没有发出参数则为所有列。
在 MSSMS 中进行了测试,SP 在有参数和无参数的情况下都能正常工作。我已经在 Visual Studio 中编写了函数,并使用 Mock Lambda 测试工具进行了测试。如果没有发送参数,那么我会得到一个完整的用户列表。但是,当我尝试传递参数时,reader 执行但 returns 没有结果。我已经检查并三次检查了参数名称和值,两者都应该有效。我不明白为什么会这样?我已经在 VB.net 中这样做了数千次,从来没有遇到过问题。
代码如下:
SP:
USE [playground]
GO
/****** Object: StoredProcedure [dbo].[GetUsers] Script Date: 22/02/2021 14:29:09 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: <Author,,Name>
-- Create date: <Create Date,,>
-- Description: <Description,,>
-- =============================================
ALTER PROCEDURE [dbo].[GetUsers]
@User varchar(60) = null
AS
BEGIN
SELECT *
FROM PlayUsers
WHERE (@User IS NULL OR UName = @User)
END
C#代码:
public static class Function
{
/// <summary>
/// Run a simple SP with optinal parameter to prove concept
/// </summary>
public static object FunctionHandler(ILambdaContext context)
{
var users = "";
Console.WriteLine("*** Starting function ***");
try
{
using (SqlConnection conn = new SqlConnection(GetConnectionString()))
{
SqlCommand cmd = new SqlCommand("GetUsers", conn)
{
CommandType = CommandType.StoredProcedure
};
cmd.Parameters.AddWithValue("@User", "BearDown");
//cmd.Parameters.Add("@User", SqlDbType.VarChar).Value = "BearDown";
conn.Open();
using (SqlDataReader rdr = cmd.ExecuteReader())
{
while (rdr.Read())
{
users += ToJson(rdr);
}
}
conn.Close();
cmd.Dispose();
conn.Dispose();
}
}
catch (Exception ex)
{
Console.WriteLine($"Exception thrown: {ex}");
}
finally
{
Console.WriteLine("*** End function ***");
}
return users;
}
public static string ToJson(this SqlDataReader rdr)
{
StringBuilder sb = new StringBuilder();
StringWriter sw = new StringWriter(sb);
using (JsonWriter jsonWriter = new JsonTextWriter(sw))
{
jsonWriter.WriteStartArray();
while (rdr.Read())
{
jsonWriter.WriteStartObject();
int fields = rdr.FieldCount;
for (int i = 0; i < fields; i++)
{
jsonWriter.WritePropertyName(rdr.GetName(i));
jsonWriter.WriteValue(rdr[i]);
}
jsonWriter.WriteEndObject();
}
jsonWriter.WriteEndArray();
return sw.ToString();
}
}
}
如您所见,我尝试了 .Add 和 .AddWithValue 来添加参数,但似乎都没有传递参数。我已经逐步检查了代码,可以看到它通过 SQL Reader 执行 运行 并且没有异常命中,但它从未找到任何结果。
将监视添加到 rdr 它显示:使用参数时“枚举未产生任何结果”。但同样,在 MSSMS 中执行 SP 时,这两个值都可以正常工作。
** 更新 ** 在解决这个问题之后,我发现替换
using (SqlDataReader rdr = cmd.ExecuteReader())
{
while (rdr.Read())
{
users = rdr.ToJson();
}
}
只有
using (SqlDataReader rdr = cmd.ExecuteReader())
{
users = rdr.ToJson();
}
按要求工作。我想我会把它包装在一个 if (rdr.HasRows) 中,看起来像是一个解决方案。
您在 FunctionHandler
中调用 rdr.Read()
(“将 reader 推进到下一条记录”),然后在您从那里调用的 ToJson
函数中再次调用...我不认为这是预期的行为?你总是在那里跳过一条记录......我的建议是尝试在 FunctionHandler
.
rer.Read()