【问题标题】:Dapper.NET and stored proc with multiple result setsDapper.NET 和具有多个结果集的存储过程
【发布时间】:2011-09-13 03:51:27
【问题描述】:

有什么方法可以将 Dapper.NET 与返回多个结果集的存储过程一起使用?

在我的例子中,第一个结果集是单行单列;如果是0,则调用成功,第二个结果集将包含实际的数据行/列。 (如果它不为零,则会发生错误并且不会提供第二个结果集)

有没有机会用 Dapper.NET 来处理这个问题?到目前为止,我只拿回了那张 0 - 但仅此而已。

更新:好的,它工作正常 - 只要结果集没有。 2 是一个单一的实体:

Dapper.SqlMapper.GridReader reader = 
    _conn.QueryMultiple("sprocname", dynParams, 
    commandType: CommandType.StoredProcedure);

int status = reader.Read<int>().FirstOrDefault();
MyEntityType resultObj = reader.Read<MyEntityType>().FirstOrDefault();

现在,我还有另一个要求。

对于第二个结果集,Dapper 的多重映射(将从 SQL Server 返回的单行拆分为两个单独的实体)似乎尚不支持(至少似乎没有过载.Read&lt;T&gt; 可以处理多映射)。

如何将该行拆分为两个实体?

【问题讨论】:

标签: sql-server stored-procedures dapper multiple-resultsets


【解决方案1】:

QueryMultiple 支持处理多个结果集的能力。我们添加的唯一设计限制是完全禁用网格读取器的缓冲。这意味着整个 API 都是流式传输

在最简单的情况下,您可以使用:

var grid = connection.QueryMultiple("select 1 select 2");
grid.Read<int>().First().IsEqualTo(1);
grid.Read<int>().First().IsEqualTo(2);

在稍微复杂一点的情况下,你可以做这样疯狂的事情:

var p = new DynamicParameters();
p.Add("a", 11);
p.Add("r", dbType: DbType.Int32, direction: ParameterDirection.ReturnValue);

connection.Execute(@"create proc #spEcho
@a int
as 
begin

select @a Id, 'ping' Name, 1 Id, 'pong1' Name
select @a Id, 'ping' Name, 2 Id, 'pong2' Name
return @a
end");

var grid = connection.QueryMultiple("#spEcho", p, 
                                     commandType: CommandType.StoredProcedure);

var result1 = grid.Read<dynamic, dynamic, Tuple<dynamic, dynamic>>(
                  (a, b) => Tuple.Create((object)a, (object)b)).ToList();
var result2 = grid.Read<dynamic, dynamic, Tuple<dynamic, dynamic>>(
                  (a, b) => Tuple.Create((object)a, (object)b)).ToList();

((int)(result1[0].Item1.Id)).IsEqualTo(11);
((int)(result1[0].Item2.Id)).IsEqualTo(1);

((int)(result2[0].Item1.Id)).IsEqualTo(11);
((int)(result2[0].Item2.Id)).IsEqualTo(2);

p.Get<int>("r").IsEqualTo(11);

您需要添加此 using 语句以启用 QueryMultiple 。

using Dapper; /* to add extended method QueryMultiple public static GridReader QueryMultiple(this IDbConnection cnn, string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null); */

【讨论】:

  • 未来读者请注意:QueryMultiple 不支持 Oracle,或者更确切地说,Oracle 不支持 QueryMultiple。见stackoverflow.com/questions/1062569/…
  • 对无法使用 Oracle 表示感谢。
  • 这太棒了!有什么需要注意的地方吗?是否也将数据作为往返检索?
  • 这是否支持多线程以实现从多阅读器并行读取?
  • 您是否必须启用 MultipleActiveResultSets 才能执行此操作?要么?也许我只是不明白 MultipleActiveResultSets 的用途:)
【解决方案2】:

您尝试过QueryMultiple 方法吗?它说它应该:

执行一个返回的命令 多个结果集,并访问每个 依次

您需要添加此 using 语句以启用 QueryMultiple 。

using Dapper; /* to add extended method QueryMultiple public static GridReader QueryMultiple(this IDbConnection cnn, string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null); */

【讨论】:

  • 这个答案将受益于一个例子或一个更详细的链接。
【解决方案3】:

多个结果集。

var reader = conn.QueryMultiple("ProductSearch", param: new { CategoryID = 1 }, commandType: CommandType.StoredProcedure);
var ProductListOne = reader.Read<ProuductTbl>().ToList();
var ProductListTwo = reader.Read<ProuductTbl>().ToList();

您需要添加此 using 语句以启用 QueryMultiple 。

using Dapper; /* to add extended method QueryMultiple public static GridReader QueryMultiple(this IDbConnection cnn, string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null); */

存储过程:

CREATE PROCEDURE [dbo].[ProductSearch]
    @CategoryID as int
AS
BEGIN
    SELECT * FROM ProductTbl
    SELECT * FROM ProductTbl
END

【讨论】:

  • Oracle 确实支持 QueryMultiple 或 QueryMultipleAsync
  • 但是它怎么知道要映射到哪个类别呢?第一次调用 Read 是否从第一个返回的结果集中拉取?
  • @Yojin 分别是的
  • 如果您需要“合并”或“拼接”单独的集合,这里有一个很好的帮助方法。 stackoverflow.com/questions/6379155/…
  • 哪些变化取决于您是否包含.ToList()?我看到您和@Sam Saffron 都在您的代码示例中完成了它。它对往返次数或返回的数据量有影响吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-07
  • 2011-04-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多