从 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
您现在只有一个结果集,其中每一行都有整个结果集的总数。
我有这个 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
您现在只有一个结果集,其中每一行都有整个结果集的总数。