SQLDataReader 在 ExecuteReader 之后读取为空
Posted
技术标签:
【中文标题】SQLDataReader 在 ExecuteReader 之后读取为空【英文标题】:SQLDataReader with an empty Read after ExecuteReader 【发布时间】:2014-05-26 11:44:44 【问题描述】:请帮助纠正我的想法,我怀疑这要么是一个明显的错误,要么是对如何从存储过程中读取的误解。
我试图让 c# 调用存储过程并返回多行。如果我删除阅读器并使用
,它适用于具有单个实例的 IDres = cmd.ExecuteNonQuery();
但在下面的代码中,while 部分只是被跳过了,我不明白为什么。我一直在玩代码并且没有任何运气。字段计数为零但表中有数据?
using (SqlConnection conn = new SqlConnection(connectionString))
conn.Open();
try
using (SqlCommand cmd = new SqlCommand("dbo.ReadFromArchive", conn))
cmd.CommandTimeout = 1000; //This should be the max timeout.
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.Parameters.Add("@ArchiveID", SqlDbType.Char).Value = AD.ArchiveID;
cmd.Parameters.Add("@DocsKEY", SqlDbType.Char, 36).Direction = ParameterDirection.Output;
cmd.Parameters.Add("@DocsDateKey", SqlDbType.DateTime).Direction = ParameterDirection.Output;
cmd.Parameters.Add("@DocumentType", SqlDbType.VarChar, 100).Direction = ParameterDirection.Output;
cmd.Parameters.Add("@OperationType", SqlDbType.VarChar, 30).Direction = ParameterDirection.Output;
try
SqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
AD.AddDocKey((string)cmd.Parameters["@DocsKEY"].Value);
AD.AddDateKey((DateTime)cmd.Parameters["@DocsDateKey"].Value);
AD.AddDocument((string)cmd.Parameters["@DocumentType"].Value);
AD.AddOpType((string)cmd.Parameters["@OperationType"].Value);
AD.RTKD = res;
AD.RTMSG = "";
catch (Exception ex)
AD.RTMSG = ex.ToString();
Logger.LogError("1. Error with executing dbo.ReadFromArchive Stored Procedure", ex);
conn.Close();
catch (Exception ex)
AD.RTMSG = ex.ToString();
Logger.LogError("Error setting up dbo.ReadFromArchive Stored Procedure :", ex);
return AD;
存储过程
ALTER PROCEDURE [dbo].[ReadFromArchive]
(
@ArchiveID CHAR(36) ,
@DocsKEY CHAR(36) OUT,
@DocsDateKey DATETIME OUT,
@DocumentType VARCHAR(100) OUT,
@OperationType VARCHAR(30) OUT
)
AS
BEGIN
Select @DocsKEY = DocsKEY from dbo.ArchiveData where ArchiveID = @ArchiveID
Select @DocsDateKey = DocsDateKey from dbo.ArchiveData where ArchiveID = @ArchiveID
Select @DocumentType = DocumentType from dbo.ArchiveData where ArchiveID = @ArchiveID
Select @OperationType = OperationType from dbo.ArchiveData where ArchiveID = @ArchiveID
END
当我在没有存储过程的情况下直接查询 SQL 时,我给它的键(ArchiveID)返回两个单独的值。如果我删除阅读器,我会毫无问题地得到一个值。现在我需要对其进行迭代,因为数据库的每个 ID 都会有很多值。
不会抛出任何错误,只是不会返回任何数据。我的理解是读者应该遍历每一行,为什么不呢?我该如何解决?
【问题讨论】:
为什么要四选一?相反,您可以将其放入表中并将其返回给 C# 可以修改SP吗?是否有任何其他组件/系统依赖它? 是的,您可以修改 SP 我是原作者,目前它只在代码中的其他地方使用。我需要返回一个,返回多个,并返回所有匹配两个参数的值。主键是两个参数 ArchiveID 和 DocumentType。 【参考方案1】:你做错了,你没有从reader
读取数据:
在while循环中应该是这样的:
AD.AddDocKey(reader["DocsKEY"].ToString());
更新:
我没有注意到 Store Procedure 中的 OUT
参数。
这是Using a DataReader to Process the RETURN Value and OUTPUT Parameters 上的 MSDN 参考。
SqlDataReader reader = cmd.ExecuteReader(CommandBehavior.CloseConnection);
reader.Close();
AD.AddDocKey((string)cmd.Parameters["@DocsKEY"].Value);
AD.AddDateKey((DateTime)cmd.Parameters["@DocsDateKey"].Value);
AD.AddDocument((string)cmd.Parameters["@DocumentType"].Value);
AD.AddOpType((string)cmd.Parameters["@OperationType"].Value);
AD.RTKD = res;
AD.RTMSG = "";
【讨论】:
没有。我没有注意到SP中的OUT
参数。【参考方案2】:
修改你的SP
ALTER PROCEDURE [dbo].[ReadFromArchive]
(
@ArchiveID CHAR(36)
)
AS
BEGIN
Select DocsKEY, DocsDateKey,DocumentType ,OperationType from dbo.ArchiveData where ArchiveID = @ArchiveID
END
然后您可以按如下方式获取 while 循环内的列
reader["reader"].ToString();
【讨论】:
@st4hoo 他是对的,不是吗?在带有out
参数的当前设置中,每个参数只返回一个值。 OP想要读取从SP返回的多行,这需要不同的设置,例如,参数变为列
如果数据库的每个 ID 有很多值,那么您不能将它们放入 @variable 中,可以吗?
@Me.Name:也许他是对的。这取决于对以下问题的回答:“SP 修改可能吗?”。
@st4hoo 同意,但如果不同意,他对Now I need to make it iterate because the database will have many values per ID.
的查询在当前 sp 和修改代码以使用阅读器是多余的情况下是不可能的。
@JonathanP out 参数将返回一个值,这也体现在需要在读取值之前关闭阅读器:它们是最后一个返回值,而不是每个返回的行。尽管理论上可以连接这些值,在参数中返回这些值,然后在代码中再次拆分它们,但这需要更改存储过程,在这种情况下,恕我直言,遵循 Mohameds 示例并让存储过程返回要容易得多一个表格,可以在阅读器(或DataTable)中读取【参考方案3】:
在关闭SqlDataReader
之前,您无法获取输出参数值。这里是对应的KB。
【讨论】:
以上是关于SQLDataReader 在 ExecuteReader 之后读取为空的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 SqlDataReader 在结构数组中存储多个值