C# DataReader:Sql 批处理命令并返回结果

Posted

技术标签:

【中文标题】C# DataReader:Sql 批处理命令并返回结果【英文标题】:C# DataReader: Sql Batch Of Commands And Return Results 【发布时间】:2015-07-07 01:34:42 【问题描述】:

当我有多个 select 语句与 insert 语句或其他不返回数据集的语句分隔时,在调用 NextResult 时,DataReader 不会返回最后一个数据集。

例如,我有以下 sql 语句要通过 SqlCommand 执行到 DataReader

select * from testing;
insert into testing (test) values ('testing here');
select * from testing;

我执行sql:

IDbCommand command = MyConnection.CreateCommand();
command.CommandText = statement;
var reader = (System.Data.Common.DbDataReader)command.ExecuteReader();

我想回来:

第一个选择语句的结果集 insert 语句影响的记录 第二个选择语句的结果集

相反,我收到了第一个结果集,然后当我执行 NextResult() 时,返回的是 false

如果我运行两个后续选择,但是结果集都会返回 即。

select * from testing
select * from testing2

我尝试仅解析 ; 并分别执行命令。 但是,从长远来看,这不会奏效,因为最终我将有一个用例来提交匿名查询或创建一个在命令中包含分号的存储过程。

如何遍历具有混合数据结果和没有返回的查询的DataReader

【问题讨论】:

这是哪个数据库?您使用的是哪个提供商软件?您是否尝试过将语句包装在存储过程代码块中?它实际上可能比您预期的要好。 @sstan 我一直在针对 postgres 数据库进行测试。我尝试使用 npgsql.net 和 odbc 驱动程序执行,结果相同。此实用程序将允许用户键入查询,因此将其放入存储过程不会很不幸。 我正在使用不可知的Common 命名空间,希望也能支持多个服务器(mysql、sqlserver)。 【参考方案1】:

我最终求助于使用DbDataAdapter 并将相应的数据加载到内存中,而不是使用DbDataReader。对于我的应用程序,这工作正常。

DataAdapter 处理获取 DataTables 并运行插入等操作。

这是一个类似于我最终做的代码sn-p:

var command = Connection.CreateCommand();
command.CommandType = CommandType.Text;
command.CommandText = statement;
DataSet set = new DataSet();
var da = CreateDataAdapter(connection);
da.SelectCommand = command;
var recordsEffected = da.Fill(set);
foreach (DataTable newTable in set.Tables)
    //do stuff with data returned

【讨论】:

【参考方案2】:

在插入测试值之前,您应该暂时存储第一个查询的结果。

SQL 服务器:

DECLARE @temp TABLE
([test] VARCHAR(20)) -- change type depending on your needs.

INSERT INTO @temp
SELECT *
FROM testing

SELECT * FROM @temp  -- first result
SELECT * FROM testing

PostgreSQL:

CREATE TEMP TABLE temp1 ON COMMIT DROP AS
SELECT *
FROM testing

INSERT INTO testing (test) VALUES ('testing here');

SELECT * FROM temp1  -- first result
SELECT * FROM testing

【讨论】:

这适用于上述特定情况。然而,该工具是一个 sql 实用程序,将支持基本未知的 sql 输入。如果可以找到,我想要一个 c# 解决方案。 哦,我明白你的意思了。我假设插入使先前的 SELECT 无效,因此要返回结果,因此需要将其存储在内存中。我不确定具体的 c# 方式。 我仍然认为这是一个很好的解决方案,尽管不适用于我的特定用例。我相信这个解决方案将适用于其他人后来偶然发现这篇文章。谢谢! 问题在于,我不确定您的“临时”表在存储过程之外是暂时的,所以我相信它保留在“临时数据库”中。由于您不能在此语句的末尾删除临时表,因为它会弄乱您的结果,我认为需要一个不同的解决方案。可能是存储过程。 @JustinRusso 好点 - 只要会话存在,#temp 就会存在。我已经更新了。【参考方案3】:

看看这里,在 SqlDataReader.NextResult 方法...

https://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqldatareader.nextresult.aspx

IDbCommand command = MyConnection.CreateCommand();
command.CommandText = statement;
var reader = command.ExecuteReader();

while(reader.Read())
    //Logic for first result


reader.NextResult();

while(reader.Read())
    //Logic for second result

【讨论】:

这是我用来迭代的,但是,如果中间有非查询语句(例如插入语句),那么第二个查询不会返回。例如以下三个查询:select、insert、select。最后一个选择没有返回 NextResult 它在插入时返回 false

以上是关于C# DataReader:Sql 批处理命令并返回结果的主要内容,如果未能解决你的问题,请参考以下文章

Sql Datareader 空值

在 C# 中将 SQL Datareader 转换为数据集

C#利用SqlDataReader读取SQL Server数据表

Sql 直接从 DataReader 中选择

从 SQL Datareader JavaScript 解析和格式化 JSON 数组

如何将 datareader 授予 sql 角色?