Dapper.NET i przechowywane procesy z wieloma zestawami wyników

80

Czy istnieje sposób na użycie Dapper.NET ze składowanymi procesami, które zwracają wiele zestawów wyników?

W moim przypadku pierwszy zestaw wyników to pojedynczy wiersz z jedną kolumną; jeśli tak, 0to wywołanie się powiodło, a drugi zestaw wyników będzie zawierał rzeczywiste wiersze / kolumny danych. (a jeśli było niezerowe, wystąpił błąd i nie zostanie dostarczony drugi zestaw wyników)

Jest jakaś szansa, aby sobie z tym poradzić dzięki Dapper.NET? Jak dotąd wracam tylko do tego singla 0- ale nic więcej.

Aktualizacja: OK, działa dobrze - o ile zestaw wyników nr. 2 to pojedynczy podmiot:

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

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

Teraz mam jeszcze jeden wymóg.

Wielokrotne mapowanie Dappera (dzielenie pojedynczego wiersza zwracanego z SQL Server na dwie oddzielne jednostki) dla tego drugiego zestawu wyników nie wydaje się być jeszcze obsługiwane (przynajmniej nie wydaje się, aby było to przeciążenie, .Read<T>które mogłoby obsłużyć multi-mapping).

Jak mogę podzielić ten wiersz na dwie jednostki?

marc_s
źródło
Jeśli chcesz scalić lub „zszyć ze sobą” oddzielne zestawy wyników ... czyli kolekcje w kodzie dotnet po serializacji, oto świetna metoda pomocnicza. stackoverflow.com/questions/6379155/…
granadaCoder

Odpowiedzi:

69

Czy wypróbowałeś tę QueryMultiplemetodę? Mówi, że powinno:

Wykonaj polecenie, które zwraca wiele zestawów wyników i uzyskuj do nich dostęp po kolei

Będziesz musiał dodać tę instrukcję using, aby włączyć 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); */
Andomar
źródło
27
W tej odpowiedzi przydałby się przykład lub łącze zawierające więcej szczegółów.
Trevor.Screws
126

QueryMultipleobsługuje zdolność radzenia sobie z wieloma zestawami wyników. Jedynym ograniczeniem projektowym, które dodaliśmy, było całkowite wyłączenie buforowania dla czytnika siatki. Oznacza to, że całe API jest przesyłane strumieniowo .

W najprostszym przypadku możesz użyć:

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

W nieco bardziej wyrafinowanym przypadku możesz robić takie szalone rzeczy:

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);

Będziesz musiał dodać tę instrukcję using, aby włączyć 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); */
Sam Saffron
źródło
23
Uwaga dla przyszłych czytelników: QueryMultiple nie obsługuje Oracle, a raczej Oracle nie obsługuje QueryMultiple. Zobacz stackoverflow.com/questions/1062569/…
Charles Burns
21
Wyrazy uznania za utknięcie w używaniu Oracle.
Pure.Krome
2
to jest świetne! czy są jakieś zastrzeżenia, na które należy zwrócić uwagę? Czy dane są pobierane jako jedna podróż w obie strony?
scgough
czy to obsługuje wielowątkowość, aby umożliwić równoległe odczytywanie z wielu czytników?
barakcaf
Czy musisz włączyć MultipleActiveResultSets, aby to zadziałało? Lub? Może po prostu nie rozumiem, do czego służy MultipleActiveResultSets :)
mslot
24

Zestaw wielu wyników.

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();

Będziesz musiał dodać tę instrukcję using, aby włączyć 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); */

Procedura składowana:

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
Arun Prasad ES
źródło
1
Oracle obsługuje QueryMultiple lub QueryMultipleAsync
Umar Topia
1
Ale skąd ma wiedzieć, do której kategorii należy go przypisać? Czy przy pierwszym wywołaniu Read pull z pierwszego zwróconego zestawu wyników?
WhiteleyJ
1
@Yojin Yes, odpowiednio
Arun Prasad ES
1
Jeśli potrzebujesz „scalić” lub „zszyć” oddzielne kolekcje, oto świetna metoda pomocnicza. stackoverflow.com/questions/6379155/…
granadaCoder
Jakie zmiany zależą od tego, czy uwzględnisz .ToList()? Widzę, że zarówno ty, jak i @Sam Saffron zrobiliście to w swoich próbkach kodu. Czy ma to wpływ na liczbę podróży w obie strony lub ilość zwróconych danych?
mft25