【发布时间】:2021-05-24 19:50:00
【问题描述】:
我正在使用 AWS RDS/Lambda/API Gateway 学习/构建 API。 DB 是 MSSQL,因为我们过去一直使用 SQL 数据库,而 Lambda 是在 Visual Studio 中用 C#(我也是 C# 的新手)编写的。
我已经用一个简单的虚拟用户表设置了一个测试数据库,并编写了一个基本的 SP 来获取数据。 SP 采用单个可选参数“用户”并返回找到该用户的所有列,如果没有发出参数,则返回所有列。
在 MSSMS 中进行了测试,SP 可以在有参数和没有参数的情况下工作。我已经在 Visual Studio 中编写了该函数,并使用 Mock Lambda 测试工具进行了测试。如果没有发送参数,那么我会得到一个完整的用户列表。但是,当我尝试传递参数时,阅读器执行但不返回任何结果。我已经检查并三次检查了参数名称和值,两者都应该是有效的。我不明白为什么会发生这种情况?我在 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 阅读器中运行良好,没有遇到异常,但它从未找到任何结果。
在 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) 中,看起来像一个解决方案。
【问题讨论】:
-
仅供参考,当您拥有
using (SqlConnection conn ...时,您无需致电conn.Close()和/或conn.Dispose(),因为这是由using处理的 -
@HansKesting 谢谢,我不确定。我 vb.net 时代的旧习惯
-
您是否从数据库中获取每一行?仔细检查是否在 c# 中看到“BearDown”
-
您的代码看起来正确,但您应该使用
Add并传递正确的长度。使用StringBuilder也有点奇怪,但对于其余的行不要挂在上面。当你说它通过阅读器时,它实际上是像接收行一样循环,还是跳过循环? -
@TonyLaw:在 VB.NET 中使用
using也是正确的方法,因为它的价值。使用AddWithValue作为参数通常是不受欢迎的。它通常有效,但偶尔会让您感到惊讶。以dbdelta.com/addwithvalue-is-evil为例
标签: c# sql amazon-web-services aws-lambda ado.net