从 SP 中读取多个 SELECT 返回的多个值

Read multiple values returned by multiple SELECT from a SP

我有这个 SP(为展示而极度简化)

SELECT colA, colB, colC
INTO #MyTable

select COUNT(*) from #MyTable

在 C# 方面,我有

int total = 0;
var command = _context.CreateStoreCommand(
    "dbo.mySP",
    CommandType.StoredProcedure,
    new SqlParameter("Param1", parameters.Param1),
    //...
);

using (command.Connection.CreateConnectionScope())
{
    using (var reader = command.ExecuteReader())
    {
        result = new Materializer<MyType>()
            .Materialize(reader)
            .ToList();

            if (reader.NextResult() && reader.Read())
            {
                // This returns the total number of elements, 
                // (select COUNT(*) from #MyTable, ~15000 in my case)
                total = reader.GetInt32(0); 
            }
        }
    }

由于SP可能会产生大量数据,.Materialize(reader)只return将前10个元素放入result变量中
绝对没有办法更改此规则 由于某些原因我无法在此处解释。

然而,在上面的示例中,total 是 SP 的结果总数,它可能大于 10(在我的例子中是 ~15000)并且效果很好。

我现在需要return另一个结果,比方说

SELECT COUNT(*) from #MyTable WHERE colA = 'sample value'

显然,我不能在 C# 端执行此操作,例如 var x = result.Where(x => x.Prop = "sample value").Count(),因为它只会搜索前 10 个结果,而 我希望它搜索整个数据集,这里是 ~15000。

我尝试添加

var total2 = reader.GetInt32(1);

但是 reader.GetInt32(1) 系统地发射了一个 System.OutOfRangeException

我如何在 C# 端读取另一个结果 return 由我的 SP 上的新 SELECT 语句编辑?

要接收第三个结果集,您需要再次调用 NextResult

if (reader.NextResult() && reader.Read())
{
    total2 = reader.GetInt32(0); 
}

尽管我建议您只更改第二个查询以使用条件聚合(一起执行会更高效):

select COUNT(*), COUNT(CASE WHEN colA = 'sample value' THEN 1 END)
from #MyTable

然后您可以使用您的原始代码:

if (reader.NextResult() && reader.Read())
{
    total = reader.GetInt32(0);
    total2 = reader.GetInt32(1); 
}

您也可以完全删除临时 table 并只使用窗口计数

SELECT colA, colB, colC,
    COUNT(*) OVER (),
    COUNT(CASE WHEN colA = 'sample value' THEN 1 END) OVER ()
FROM Whatever

您现在只有一个结果集,其中每一行都有整个结果集的总数。