¿El control de gridview no se actualiza?

¿El control de gridview no se actualiza?

Tengo lo que espero sea una pregunta sencilla. Tengo un control gridview que está enlazado a un sqldatasource.

Primero, el código relevante:

<asp:DropDownList ID="cboCustomerID" runat="server"
    DataSourceID="DataSourceCustomer" DataTextField="CustomerName" DataValueField="CustomerID">
</asp:DropDownList>
<asp:DropDownList ID="cboStaffID" runat="server"
    DataSourceID="DataSourceStaff" DataTextField="StaffFullName" DataValueField="StaffID">
</asp:DropDownList>
<div><gcctl:MyCheckBox ID="chkShowClosed" Text="Show Closed Jobs?" Checked="false" AutoPostBack="true" runat="server" /></div>
<div><asp:Button ID="btnSearch" runat="server" OnClick="btnSearch_Click" Text="Search" /></div>

<div id="customersearchresults" class="searchresults">
    <asp:SqlDataSource id="gvJobsDataSource" runat="server" ConnectionString="<%$ ConnectionStrings:GeekCommandConnString %>"
        SelectCommand="SELECT j.JobID, j.JobName, s.JobStatus, jal.[JobAssignmentsFullList]
            FROM (SELECT * FROM [dbo].[Jobs] WHERE ((NULLIF(@CustomerSearch,'') IS NOT NULL AND CustomerID = @CustomerSearch) OR (NULLIF(@CustomerSearch,'') IS NULL))) j
            INNER JOIN (SELECT * FROM [list].[JobStatuses] WHERE ((@ShowClosed = 0 AND IsStatusOpen = 1) OR (@ShowClosed = 1)) AND IsActive = 1) s ON j.JobStatusID = s.JobStatusID
            LEFT JOIN (SELECT * FROM [dbo].[JobAssignments] WHERE ((NULLIF(@StaffSearch,'') IS NOT NULL AND StaffID = @StaffSearch) OR (NULLIF(@StaffSearch,'') IS NULL))) ja ON j.JobID = ja.JobID
            LEFT JOIN [dbo].[udv_JobAssignmentsCommaDelimited] jal ON j.JobID = jal.JobID
            ">
        <SelectParameters>
            <asp:Parameter Name="CustomerSearch" Type="Int32" />
            <asp:Parameter Name="StaffSearch" Type="Int32" />
            <asp:Parameter Name="ShowClosed" Type="Boolean" />
        </SelectParameters>
    </asp:SqlDataSource>

    <asp:GridView ID="gvJobs" runat="server" AllowSorting="True"  
        AutoGenerateColumns="False"
        DataKeyNames="JobID"
        DataSourceID="gvJobsDataSource"
        AutoGenerateDeleteButton="False"    
        AutoGenerateEditButton="False" 
        AutoGenerateSelectButton="False"
        CssClass="searchresultsgrid" 
        AllowPaging="True" PageSize="50"
        OnRowCommand="gvJobs_RowCommand"
        EmptyDataText="No matching jobs on record." >
        <Columns>
            <asp:templatefield>
                <itemtemplate>
                    <asp:linkbutton id="btnEdit" runat="server" CommandName="JobEdit" OnClientClick="PageForm.target ='_blank';" text="View/Edit" />
                </itemtemplate>
            </asp:templatefield>

            <asp:BoundField DataField="JobID" HeaderText="ID" InsertVisible="false" ReadOnly="true" Visible="false" SortExpression="JobID" />
            <asp:templateField HeaderText="Job Name" SortExpression="JobName">
                <ItemTemplate><%# Eval("JobName") %></ItemTemplate>
            </asp:templateField>
            <asp:templateField HeaderText="Assigned to" SortExpression="JobAssignmentsFullList">
                <ItemTemplate><%# Eval("JobAssignmentsFullList") %></ItemTemplate>
            </asp:templateField>
        </Columns>
    </asp:GridView>
</div>


<asp:SqlDataSource ID="DataSourceCustomer" runat="server"
    ConnectionString="<%$ ConnectionStrings:GeekCommandConnString %>" 
    SelectCommand="SELECT NULL AS [CustomerID]
                , NULL AS [CustomerName]
            UNION SELECT [CustomerID]
                ,[CustomerName]
            FROM [GeekCommand].[dbo].[Customers]
            WHERE ((@ShowInactive = 0 AND IsActive = 1) OR (@ShowInactive = 1))
            ORDER BY CustomerName">
    <SelectParameters>
        <asp:ControlParameter Name="ShowInactive" Type="Boolean" ControlID="chkCustomersShowInactive" PropertyName="Checked" />
    </SelectParameters>
</asp:SqlDataSource>
<asp:SqlDataSource ID="DataSourceStaff" runat="server"
    ConnectionString="<%$ ConnectionStrings:GeekCommandConnString %>" 
    SelectCommand="SELECT NULL AS [StaffID]
                , NULL AS [StaffFullName]
            UNION SELECT [StaffID]
                ,COALESCE([FirstName], [Nickname], '') + ' ' + COALESCE([LastName], '') AS StaffFullName
            FROM [GeekCommand].[dbo].[Staff]
            WHERE ((@ShowInactive = 0 AND IsActive = 1) OR (@ShowInactive = 1))
            ORDER BY StaffFullName">
    <SelectParameters>
        <asp:ControlParameter Name="ShowInactive" Type="Boolean" ControlID="chkStaffShowInactive" PropertyName="Checked" />
    </SelectParameters>
</asp:SqlDataSource>

Y el código aspx.cs relevante:

int? iCustomerID;
int? iStaffID;

//--------
protected void SetIDs()
{
    this.iCustomerID = null;
    this.iStaffID = null;

    if (Request.QueryString["customerid"] != null) //new customer
    {
        try
        {
            this.iCustomerID = Convert.ToInt32(Request.QueryString["customerid"]);
        }
        catch { }
    }

    if (Request.QueryString["staffid"] != null) //new customer
    {
        try
        {
            this.iStaffID = Convert.ToInt32(Request.QueryString["staffid"]);
        }
        catch { }
    }

    if (iCustomerID != null)
    {
        cboCustomerID.SelectedValue = iCustomerID.ToString();
    }

    if (iStaffID != null)
    {
        cboStaffID.SelectedValue = iStaffID.ToString();
    }
}

//--------
protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        SetIDs();
    }
}

//--------
protected void btnSearch_Click(object sender, EventArgs e)
{
    gvJobsDataSource.SelectParameters["CustomerSearch"].DefaultValue = cboCustomerID.SelectedValue.ToString();
    gvJobsDataSource.SelectParameters["StaffSearch"].DefaultValue = cboStaffID.SelectedValue.ToString();
    gvJobsDataSource.SelectParameters["ShowClosed"].DefaultValue = chkShowClosed.Checked.ToString();

    gvJobs.DataBind();
}

Cuando ejecuto lo siguiente en SSMS, obtengo 2 filas, como debería:

DECLARE @CustomerSearch int, @StaffSearch int, @ShowClosed bit
SELECT @CustomerSearch = 2331, @StaffSearch = '', @ShowClosed = CAST(0 AS bit)

SELECT j.JobID, j.JobName, s.JobStatus, jal.[JobAssignmentsFullList]
FROM (SELECT * FROM [dbo].[Jobs] WHERE ((NULLIF(@CustomerSearch,'') IS NOT NULL AND CustomerID = @CustomerSearch) OR (NULLIF(@CustomerSearch,'') IS NULL))) j
INNER JOIN (SELECT * FROM [list].[JobStatuses] WHERE ((@ShowClosed = 0 AND IsStatusOpen = 1) OR (@ShowClosed = 1)) AND IsActive = 1) s ON j.JobStatusID = s.JobStatusID
LEFT JOIN (SELECT * FROM [dbo].[JobAssignments] WHERE ((NULLIF(@StaffSearch,'') IS NOT NULL AND StaffID = @StaffSearch) OR (NULLIF(@StaffSearch,'') IS NULL))) ja ON j.JobID = ja.JobID
LEFT JOIN [dbo].[udv_JobAssignmentsCommaDelimited] jal ON j.JobID = jal.JobID

Pero cuando selecciono un cliente (específicamente el cliente cuya identificación es 2331) en modo de depuración y paso por el código btnSearch_Click, cboCustomerID.SelectedValue = "2331", cboStaffID.SelectedValue = "", chkShowClosed.Checked = false (todos de lo cual es correcto)... pero no pasa nada cuando paso el comando databind. La vista de cuadrícula continúa mostrando "No hay trabajos coincidentes registrados".

Siento que me estoy perdiendo algo realmente obvio, pero por mi vida no puedo averiguar qué es.

ACTUALIZACIÓN: Bien. Esto es interesante. Aparentemente, la consulta nunca se envía al servidor SQL. Acabo de iniciar SQL Server en modo de seguimiento, recargué la página aspx e hice una búsqueda, y aunque las consultas que están detrás de las dos listas desplegables están en el registro, la consulta que está detrás de la vista de cuadrícula simplemente no está allí.

ACTUALIZACIÓN n.º 2: he reemplazado los parámetros de selección con los siguientes:

<asp:ControlParameter Name="CustomerSearch" ControlID="cboCustomerID" PropertyName ="SelectedValue" />
<asp:ControlParameter Name="StaffSearch" ControlID="cboStaffID" PropertyName ="SelectedValue" />
<asp:ControlParameter Name="ShowClosed" Type="Boolean" ControlID="chkShowClosed" PropertyName="Checked" />

... y eliminó el código adicional en el evento btnSearch_Click, por lo que la única línea en ese código es:

protected void btnSearch_Click(object sender, EventArgs e)
{
    gvJobs.DataBind();
}

...sin cambios. Todavía no sucede nada cuando hago clic en el botón de búsqueda.

Mostrar la mejor respuesta

Actualización rápida: después de publicar, descubrí que tenía la propiedad DataKeyNames de la vista de cuadrícula configurada incorrectamente. Lo he actualizado a DataKeyNames="JobID". (actualizará la publicación con el nuevo código). Sin embargo, no solucionó este problema en particular.

Lo primero que arreglaría es ese antipatrón que tienes ahí al que llamo "Try/Squelch". Lo único peor que no manejar los errores es detectarlos y fingir que no pasó nada. Esa consulta que tienes ahí me hace negar con la cabeza. ¿Por qué todas las subconsultas? Pondría una captura de prueba dentro de su método, con una captura real. Luego pase y vea lo que sucede.

Es posible que desee ejecutar un seguimiento de sql y ver qué valores reales también está pasando al servidor sql.

Gracias, Sean. Re: los intentos/capturas... en este caso particular, realmente quiero probar/squelch. El propósito es capturar las cadenas de consulta, si existen, y si se llaman correctamente (como siempre se hará cuando se llamen desde el código), luego guárdelas y seleccione los valores apropiados en los menús desplegables. Dado que las cadenas de consulta son opcionales, no quiero que se equivoquen... el resultado de que estén ausentes o no sean numéricos es que nada se selecciona automáticamente en los menús desplegables. No está relacionado con este tema.

Con respecto a SQL Trace: Buen plan. :) Veré si es posible hacer eso (usando SQL Server Express 2014)

Me doy cuenta de que es parte de este problema, pero esa es una mala práctica de codificación. Las excepciones son caras desde el punto de vista del rendimiento. Envuélvalos en una declaración if en su lugar. If(Request.QueryString["YourString"]) no es nulo.

Si tiene Profiler, puede conectarse sin ningún problema.

Actualización: Bien. Esto es interesante. Aparentemente, la consulta nunca se envía al servidor SQL. Acabo de cargar la página e hice una búsqueda, y aunque las consultas que están detrás de las dos listas desplegables están en el registro, la consulta que está detrás de la vista de cuadrícula simplemente no está allí.

¿Se supone que el SelectParameters proviene de los controles de la página?

Sí lo son. Actualmente, son parámetros que se completan durante el código btnSearch_Click. Los tenía como asp:controlparameters, pero eso fue lo primero que cambié para tratar de solucionar este problema.

Otra actualización: hice algunos cambios (descubrí que mis campos de plantilla estaban equivocados y también cambié los parámetros de selección de nuevo a parámetros de control). La pregunta se actualiza con el nuevo código. Todavía no hay cambios... el código btnSearch todavía no hace nada. :(

¡Sí! Encontré la respuesta: https://forums.asp.net/t/1243253. aspx?Gridview+Databind+No+Funciona

El problema era que las vistas de cuadrícula tenían una propiedad: CancelSelectOnNullParameter, que es verdadera de forma predeterminada. Dado que al menos una de las listas desplegables casi siempre es nula cuando realizo la búsqueda, no sucedió nada cuando presioné el botón de búsqueda. Cuando agregué CancelSelectOnNullParameter="false" al control gridview, solucionó el problema.

(Nota semi-relacionada) También agregué lo siguiente a ControlParameters: ConvertEmptyStringToNull="true"