Dapper.NET und gespeicherter Prozess mit mehreren Ergebnismengen

79

Gibt es eine Möglichkeit, Dapper.NET mit gespeicherten Prozessen zu verwenden, die mehrere Ergebnismengen zurückgeben?

In meinem Fall ist die erste Ergebnismenge eine einzelne Zeile mit einer einzelnen Spalte. Wenn dies 0der Fall ist, war der Aufruf erfolgreich und die zweite Ergebnismenge enthält die tatsächlichen Datenzeilen / -spalten. (und wenn es nicht Null war, ist ein Fehler aufgetreten und es wird keine zweite Ergebnismenge bereitgestellt)

Gibt es eine Chance, dies mit Dapper.NET zu erledigen? Bisher bekomme ich nur diese Single zurück 0- aber nichts weiter.

Update: OK, es funktioniert einwandfrei - solange die Ergebnismenge Nr. 2 ist eine Einheit:

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

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

Jetzt habe ich noch eine weitere Anforderung.

Dappers Multi-Mapping (Aufteilen einer einzelnen von SQL Server zurückgegebenen Zeile in zwei separate Entitäten) für diese zweite Ergebnismenge scheint noch nicht unterstützt zu werden (zumindest scheint es keine Überlastung zu geben .Read<T>, die damit umgehen kann Multi-Mapping).

Wie kann ich diese Zeile in zwei Entitäten aufteilen?

marc_s
quelle
Wenn Sie die einzelnen Ergebnismengen zusammenführen oder "zusammenfügen" müssen ... auch bekannt als Sammlungen im Dotnet-Code nach der Serialisierung, finden Sie hier eine großartige Hilfsmethode. stackoverflow.com/questions/6379155/…
granadaCoder

Antworten:

69

Haben Sie die QueryMultipleMethode ausprobiert ? Es heißt, es sollte:

Führen Sie einen Befehl aus, der mehrere Ergebnismengen zurückgibt, und greifen Sie nacheinander auf jede zu

Sie müssen diese using-Anweisung hinzufügen, um QueryMultiple zu aktivieren.

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
quelle
27
Diese Antwort würde von einem Beispiel oder einem Link mit mehr Details profitieren.
Trevor.Screws
126

QueryMultipleunterstützt die Fähigkeit, mit mehreren Ergebnismengen umzugehen. Die einzige Designeinschränkung, die wir hinzugefügt haben, war das vollständige Deaktivieren der Pufferung für den Grid Reader. Dies bedeutet, dass die gesamte API gestreamt wird .

Im einfachsten Fall können Sie verwenden:

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

In dem etwas anspruchsvolleren Fall können Sie verrückte Sachen wie diese machen:

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

Sie müssen diese using-Anweisung hinzufügen, um QueryMultiple zu aktivieren.

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 Safran
quelle
23
Hinweis für zukünftige Leser: QueryMultiple unterstützt Oracle nicht bzw. Oracle unterstützt QueryMultiple nicht. Siehe stackoverflow.com/questions/1062569/…
Charles Burns
21
Lob für die Verwendung von Oracle.
Pure.Krome
2
das ist toll! Gibt es irgendwelche Vorbehalte, auf die Sie achten müssen? Werden die Daten auch als eine Hin- und Rückfahrt abgerufen?
Scgough
Unterstützt dies Multithreading, um das parallele Lesen vom Multi-Reader zu ermöglichen?
Barakcaf
Müssen Sie MultipleActiveResultSets aktivieren, damit dies ausgeführt werden kann? Oder? Vielleicht verstehe ich einfach nicht, wofür MultipleActiveResultSets verwendet wird :)
mslot
23

Mehrere Ergebnismengen.

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

Sie müssen diese using-Anweisung hinzufügen, um QueryMultiple zu aktivieren.

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

Gespeicherte Prozedur:

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
quelle
1
Oracle unterstützt QueryMultiple oder QueryMultipleAsync
Umar Topia
1
Aber woher weiß es, welche Kategorie es auch abbilden soll? Wird beim ersten Aufruf von Read aus der ersten zurückgegebenen Ergebnismenge gezogen?
WhiteleyJ
1
@ Yojin Ja, jeweils
Arun Prasad ES
1
Wenn Sie die einzelnen Sammlungen "zusammenführen" oder "zusammennähen" müssen, finden Sie hier eine hervorragende Hilfsmethode. stackoverflow.com/questions/6379155/…
granadaCoder
Welche Änderungen hängen davon ab, ob Sie die einbeziehen oder nicht .ToList()? Ich sehe, dass sowohl Sie als auch @Sam Saffron dies in Ihren Codebeispielen getan haben. Hat dies Auswirkungen auf die Anzahl der Hin- und Rückfahrten oder die Menge der zurückgegebenen Daten?
mft25