lunes, 15 de septiembre de 2014

Cuando necesitas pasar un objeto lista a un procedimiento almacenado...


Hello world,
En estos últimos días me he encontrado con la necesidad de pasar una lista de guids a un procedimiento almacenado. Para esto me planteé varias opciones:
  1. Pasar un string con toda la lista de guids concatenados y separados por comas (solución fea, fea aunque "efectiva").
  2. Crear una tabla temporal, donde previamente insertaría todos los guids, ejecutar la consulta sobre ella y posteriormente borrarla (solución más limpia pero mucho más costosa y de muchísimo peor rendimiento).
  3. Investigar un poco y ver cómo solucionar el problema...
Al final opte por el punto 3, y con seguí la siguiente solución.  Lo primero es crearte un tipo en base de datos, para esto ejecutaremos la siguiente sentencia:
CREATE TYPE [dbo].[GuidList] AS TABLE(
[Id] [uniqueidentifier] NULL
)
Con esto con seguiremos el siguiente objeto en nuestra base de datos:

 
Por otro lado, en nuestro procedimiento almacenado para utilizarlo es muy simple, En el siguiente ejemplo muestro como hacer una consulta con un “in” sobre mi tipo GuidList:
CREATE PROCEDURE [dbo].[GetCountries_ByIds] (@CountriesId GuidList READONLY)
AS
BEGIN
SELECT
       CountryId,
       CountryDescription
FROM
       Country
       CountryId IN (SELECT Id FROM @CountriesId)
END

En cuanto a la gestión de este tipo de parámetro en nuestro código, es tan sencillo como crearnos un dataTable con  la información que necesitamos pasar, y asignárselo a un parámetro:
var dtCountries = new DataTable();
dtCountries.Columns.Add("Id");
if (CountryId != null)
       CountryId.ForEach(x =>
       {
            var r = dtCountries.NewRow();
            r[0] = x;
            dtCountries.Rows.Add(r);
        });
var CountriesIdSQLParameter = new SqlParameter("@CountriesId", dtCountries);
using (var reader = this.iAdoSqlHelper.ExecuteReader(iConfiguration.ConnectionString,   SqlCommandText.SP_GetCountries_ByIds, CommandType.StoredProcedure, CountriesIdSQLParameter))
...
...
...
Con estos simples pasos, tendremos una manera más limpia y eficiente de poder pasar un objeto de tipo lista a un procedimiento almacenado.

Hasta el próximo post! 

2 comentarios:

Yuyul dijo...

Me gusta esta solución, muy limpia y sencilla. La única pega que le encuentro es si tu aplicación puede trabajar con diferentes motores de base de datos. Has investigado si Oracle permite definir tipos?

nfanjul dijo...

Hola Yuyul, en Oracle no lo he probado, y tampoco tengo ningún servidor Oracle montado para probarlo rápidamente... Investigando un poco por internet he encontrado el siguiente link que te puede ser de ayuda:

http://stackoverflow.com/questions/980421/c-pass-a-user-defined-type-to-a-oracle-stored-procedure

Espero el feedback de tus pruebas!!

;-)