Dapper.NET y proceso almacenado con múltiples conjuntos de resultados

80

¿Hay alguna forma de usar Dapper.NET con procesos almacenados que devuelven múltiples conjuntos de resultados?

En mi caso, el primer conjunto de resultados es una sola fila con una sola columna; si es así, 0la llamada fue exitosa, y el segundo conjunto de resultados contendrá las filas / columnas de datos reales. (y si no era cero, se produjo un error y no se proporcionará un segundo conjunto de resultados)

¿Alguna posibilidad de manejar esto con Dapper.NET? Hasta ahora, solo recuperaré ese single 0, pero nada más.

Actualización: OK, funciona bien, siempre que el conjunto de resultados no. 2 es una sola entidad:

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

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

Ahora tengo otro requisito.

El mapeo múltiple de Dapper (dividiendo una sola fila devuelta desde SQL Server en dos entidades separadas) para ese segundo conjunto de resultados no parece ser compatible hasta el momento (al menos no parece haber una sobrecarga .Read<T>que pueda manejar multi-mapeo).

¿Cómo puedo dividir esa fila en dos entidades?

marc_s
fuente
Si necesita fusionar o "unir" los conjuntos de resultados separados ... también conocidos como colecciones en el código dotnet después de la serialización, aquí hay un gran método auxiliar. stackoverflow.com/questions/6379155/…
granadaCoder

Respuestas:

69

¿Has probado el QueryMultiplemétodo? Dice que debería:

Ejecute un comando que devuelva múltiples conjuntos de resultados y acceda a cada uno de ellos.

Deberá agregar esta declaración using para habilitar 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
fuente
27
Esta respuesta se beneficiaría de un ejemplo o un enlace con más detalles.
Trevor.Screws
126

QueryMultipleadmite la capacidad de tratar con múltiples conjuntos de resultados. La única restricción de diseño que agregamos fue la desactivación total del almacenamiento en búfer para el lector de cuadrícula. Esto significa que toda la API se está transmitiendo .

En el caso más simple puedes usar:

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

En el caso un poco más sofisticado, puedes hacer cosas locas como esta:

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

Deberá agregar esta declaración using para habilitar 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
fuente
23
Nota para futuros lectores: QueryMultiple no es compatible con Oracle, o más bien, Oracle no es compatible con QueryMultiple. Ver stackoverflow.com/questions/1062569/…
Charles Burns
21
Condolencias por quedarse atascado con el uso de Oracle.
Pure.Krome
2
¡esto es genial! ¿Hay alguna advertencia a tener en cuenta al respecto? ¿También se recuperan los datos como un viaje de ida y vuelta?
scgough
¿Esto es compatible con subprocesos múltiples para permitir la lectura desde el lector múltiple en paralelo?
barakcaf
¿Tiene que habilitar MultipleActiveResultSets para que esto funcione? ¿O? Tal vez simplemente no entiendo para qué se usa MultipleActiveResultSets :)
mslot
24

Conjunto de resultados múltiples.

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

Deberá agregar esta declaración using para habilitar 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); */

Procedimiento almacenado:

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
fuente
1
Oracle admite QueryMultiple o QueryMultipleAsync
Umar Topia
1
Pero, ¿cómo sabe también en qué categoría mapearlo? ¿La primera vez que llama a Read, se extrae del primer conjunto de resultados devuelto?
WhiteleyJ
1
@Yojin Sí, respectivamente
Arun Prasad ES
1
Si necesita "fusionar" o "unir" las colecciones separadas, aquí hay un gran método de ayuda. stackoverflow.com/questions/6379155/…
granadaCoder
¿Qué cambios dependen de si incluye o no el .ToList()? Veo que tanto usted como @Sam Saffron lo han hecho en sus ejemplos de código. ¿Tiene alguna implicación en el número de viajes de ida y vuelta o en la cantidad de datos devueltos?
mft25