Inicio > .NET Framework, C#, Resolución de problemas > Mi fuente de datos no regresa valores con parámetros nulos

Mi fuente de datos no regresa valores con parámetros nulos


Me recargo en la pared. Benditos sean los dioses. Hoy viernes, día que deberíamos consagrar exclusivamente a Freyja (Friday, Freitag, etc.), tomando cerveza y comiendo carne asada de venado, me he topado con un problema que me ha impedido celebrar como se debe a la adorada diosa.

Pues resulta que en el trabajo, ando creando una aplicación web de geo-codificación. En esencia, la aplicación lee una base de datos de la Secretaría de Educación Pública y obtiene todas las escuelas registradas, se aplican algunos filtros según el deseo del usuario, para luego mostrarlas en un mapa de Google. Pan comido (y de muerto, ahora que comienza la temporada).

Así las cosas, el primer paso es realizar el filtro. Mi procedimiento almacenado es sencillo: un vil select con unas validaciones y listo.

create procedure SchoolSearch
    @Key nvarchar(12) = null,
    @StateId nvarchar(4) = null,
    @MunicipalityId nvarchar(5) = null,
    @Name nvarchar(82) = null
as
begin

    if (isnull(@Name, '') = '') begin set @Name = '%' end
    else begin set @Name = '%' + rtrim(@Name) + '%' end
    if (rtrim(isnull(@Key, '')) = '') begin set @Key = '%%' end
    else begin set @Key = '%' + rtrim(@Key) + '%' end
    if (isnull(@StateId, '') = '') begin set @StateId = '%' end
    else begin set @StateId = '%' + rtrim(@StateId) + '%' end
    if (isnull(@MunicipalityId, '') = '') begin set @MunicipalityId = '%' end
    else begin set @MunicipalityId = '%' + rtrim(@MunicipalityId) + '%' end

    select CCT, NOM_CCT, NOMBRETUR, TIPO, NIVEL, X, Y , ENTIDAD, NOMBREMUN
    from Escuelas
    where
        CCT like @Key
        and ENT like @StateId
        and MUNICIPIO like @MunicipalityId
        and NOM_CCT like @Name
    order by ENTIDAD, NOMBREMUN

end

¡Pffft! Papita. Segunda parte, en mi página ASP.NET, creo una vil fuente de datos usando SqlDataSource. Algo así.

<asp:SqlDataSource ID="_searchDataSource" runat="server" ConnectionString="<%$ ConnectionStrings:GeoSepAnonymousDatabase %>"
    SelectCommand="SchoolSearch" SelectCommandType="StoredProcedure">
    <SelectParameters>
        <asp:Parameter Name="Key" DbType="String" Size="12" ConvertEmptyStringToNull="false"   />
        <asp:Parameter Name="StateId" DbType="String" Size="4" ConvertEmptyStringToNull="true" />
        <asp:Parameter Name="MunicipalityId" DbType="String" Size="5" ConvertEmptyStringToNull="true" />
        <asp:Parameter Name="Name" DbType="String" Size="82" ConvertEmptyStringToNull="true" />
    </SelectParameters>
</asp:SqlDataSource>

¡Pffft! Kindergarten. Tercera parte, un poquito de código C# que actualiza la fuente de datos en base a los filtros seleccionados en otros controles (_stateList y _municipalityList son DropDownList, para finalmente hacer el DataBind sobre el GridView (_catalogueView) y mostrar todo en una ventana modal (ModalPopupExtender) del Ajax Control Toolkit (_showCataloguePopup).

protected void HandleSearchClick(object sender, EventArgs args)
{
    if (!string.IsNullOrEmpty(_stateList.SelectedValue))
        _searchDataSource.SelectParameters["StateId"].DefaultValue =
                 _stateList.SelectedValue;
    else
        _searchDataSource.SelectParameters["StateId"].DefaultValue =
                 string.Empty;

    if (!string.IsNullOrEmpty(_municipalityList.SelectedValue))
        _searchDataSource.SelectParameters["MunicipalityId"].DefaultValue =
                 _municipalityList.SelectedValue;
    else
        _searchDataSource.SelectParameters["MunicipalityId"].DefaultValue =
                 string.Empty;

    _catalogueView.DataBind();
    _showCataloguePopup.Show();
}

¡Pfft! Piece of… Scheisse! Pues sí, usando ASP.NET Framework 3.5 y C# 3, con SQL Server 2008, lo anterior no jala. Es decir, si yo selecciono un valor, me despliega los resultados como debería. Perfecto. Pero si no selecciono nada (es decir, si paso al procedimiento almacenado un valor nulo), no me regresa registro alguno.

No tiene sentido. Abro el SQL Server Management Studio, y corro el procedimiento con los cuatro parámetros en nulos. y funciona, como debe de ser. Luego, para probar que no estoy loco, me creo un SqlConnection, un SqlCommand, un SqlDataAdapter y a partir de éstos, relleno un DataSet: éste devuelve datos. Incluso si hago el enlace entre el GridView y el DataSet, todo es maravilloso. Pero no tiene sentido que no funcione el SqlDataSource. ¿Qué puede estar pasando?

Bueno, pues esto me llevó un ratillo hasta que di en el clavo. Para esto, abrí el Profiler de SQL Server 2008 y vi que no se ejecutaba ninguna consulta. Extrañado (y en este punto, ya algo molesto con el mundo) Comencé a poner mensajes y hacer rastreos, quitando propiedades y así. El problema tenía que estar en el SqlDataSource, porque demonios, todo lo demás parecía funcionar. Así que me puse a revisar todas las propiedades de este objeto. Y di con una que me llamó la atención: CanSelectOnNullParameter.

El nombre me resultó demasiado sospechoso como para ignorarlo. Así que cambié la definición de mi fuente de datos e incorporé semejante parámetro, estableciéndolo a false.

<asp:SqlDataSource ID="_searchDataSource" runat="server"
    ConnectionString="<%$ ConnectionStrings:GeoSepAnonymousDatabase %>"
    SelectCommand="SchoolSearch" SelectCommandType="StoredProcedure"
    CancelSelectOnNullParameter="false">
    <SelectParameters>
        <asp:Parameter Name="Key" DbType="String" Size="12" ConvertEmptyStringToNull="false"   />
        <asp:Parameter Name="StateId" DbType="String" Size="4" ConvertEmptyStringToNull="true" />
        <asp:Parameter Name="MunicipalityId" DbType="String" Size="5" ConvertEmptyStringToNull="true" />
        <asp:Parameter Name="Name" DbType="String" Size="82" ConvertEmptyStringToNull="true" />
    </SelectParameters>
</asp:SqlDataSource>

 

¡Y funcionó! Una vez que pasó mi anonadamiento me fui derechito a la documentación de MSDN, y encontré esto en la sección de Valor de Propiedad:

Tipo: System.Boolean.- true si se cancela una operación de la recuperación de datos cuando un parámetro contenido en la colección SelectParameters se evalúa como null; de lo contrario, false. El valor predeterminado es true.

¡Me lleva Pifas! Así que eso era: cuando uno tiene parámetros en un select y estos son nulos, el SqlDataSource simplemente decide abortar la operación. Por supuesto, si no es nulo (i.e. un espacio en blanco es suficiente) todo funciona bien. Establecer este valor a falso hace que la vida vuelva a cobrar sentido, ya que con esto no interrumpe nada y le pasa el valor nulo al procedimiento almacenado, el cual arreglará cualquier valor posible.

Así que bueno, ya no pude tomar cerveza y comer asado de venado por arreglar esto. Pero ya quedó y todo jala a las mil maravillas. Así que ya es hora de comenzar este fin de semana, y para ello pasaré al mercado por una enorme calabaza para hacerla zumo con lo que acompañaré mi pan de muerto.

Anuncios
  1. Sandy
    octubre 30, 2012 en 8:53 pm

    :) Muchas gracias me ha servido

  1. No trackbacks yet.

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s