Dapper.NET и хранимая процедура с несколькими наборами результатов

80

Есть ли способ использовать 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<T>которая может обрабатывать мульти-отображение).

Как я могу разбить эту строку на две части?

marc_s
источник
Если вам нужно объединить или «сшить вместе» отдельные наборы результатов ... то есть коллекции в коде dotnet после сериализации, вот отличный вспомогательный метод. stackoverflow.com/questions/6379155/…
granadaCoder

Ответы:

69

Вы пробовали 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); */
Андомар
источник
27
Для этого ответа было бы полезно привести пример или ссылку с более подробной информацией.
Trevor.Screws
126

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); */
Сэм Шафран
источник
23
Примечание для будущих читателей: QueryMultiple не поддерживает Oracle, точнее, Oracle не поддерживает QueryMultiple. См. Stackoverflow.com/questions/1062569/…
Чарльз Бернс,
21
Приветствую вас за то, что вы застряли в использовании Oracle.
Pure.Krome
2
это замечательно! есть ли предостережения по этому поводу? Также извлекаются ли данные за один рейс туда и обратно?
scgough
поддерживает ли это многопоточность, чтобы обеспечить параллельное чтение с мульти-ридера?
barakcaf 07
Вам нужно включить MultipleActiveResultSets для этого? Или же? Может, я просто не понимаю, для чего используется MultipleActiveResultSets :)
mslot
24

Множественный набор результатов.

var reader = conn.QueryMultiple("ProductSearch", param: new { CategoryID = 1, SubCategoryID = "", PageNumber = 1 }, commandType: CommandType.StoredProcedure);
var CategoryOneList = reader.Read<CategoryOne>().ToList();
var CategoryTwoList = reader.Read<CategoryTwo>().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 varchar(20),
    @SubCategoryID as varchar(20),
    @PageNumber as varchar(20)
AS
BEGIN
    SELECT * FROM ProductTbl
    SELECT * FROM ProductTbl
END
Арун Прасад ES
источник
1
Oracle действительно поддерживает QueryMultiple или QueryMultipleAsync
Умар Топия,
1
Но как он узнает, в какую категорию его сопоставить? При первом вызове Read извлекается ли из первого возвращенного набора результатов?
WhiteleyJ
1
@Yojin Да, соответственно
Арун Прасад ES
1
Если вам нужно «объединить» или «сшить» отдельные коллекции, вот отличный вспомогательный метод. stackoverflow.com/questions/6379155/…
granadaCoder
Какие изменения зависят от того, включены ли вы .ToList()? Я вижу, что и вы, и @Sam Saffron сделали это в своих примерах кода. Влияет ли это на количество циклов приема-передачи или объем возвращаемых данных?
mft25