基于不返回数据的 DatePicker 过滤 Web 窗体 GridView

Filtering Web Forms GridView based on DatePicker not returning data

我有一个带有 gridview 和两个日期选择器的 Web 表单以及一个用于提交具有日期时间约束的新查询的提交。作为过滤数据的开始和结束日期。在没有数据的情况下,数据加载正常,当单击具有所选日期的提交按钮时,没有任何反应。我想知道过滤后的数据是否未正确绑定(我是网络表单和 gridview 的新手。) 这是页面的隐藏代码:

protected void Page_Load(object sender, EventArgs e)
    {
        if (!Page.IsPostBack)
            BindDataToGridView();
    }

    protected void dashboard_RowEditing(object sender, GridViewEditEventArgs e)
    {
        gridErrors.Text = string.Empty;
        dashboard.EditIndex = e.NewEditIndex;
        BindDataToGridView();
    }

    protected void dashboard_RowCancelingEdit(object sender, GridViewCancelEditEventArgs e)
    {
        dashboard.EditIndex = -1;
        BindDataToGridView();
    }
    protected void dashboard_PageIndexChanging(object sender, GridViewPageEventArgs e)
    {
        dashboard.PageIndex = e.NewPageIndex;
        BindDataToGridView();
    }
    protected void dashboard_RowUpdating(object sender, GridViewUpdateEventArgs e)
    {
        gridErrors.Text = string.Empty;
        GridViewRow tabRow = (GridViewRow)dashboard.Rows[e.RowIndex];
        HiddenField hdnTabId = (HiddenField)tabRow.FindControl("hdnTabId");
        TextBox TxtName = (TextBox)tabRow.Cells[1].Controls[0];
    }

    protected void button1_Click(object sender, EventArgs e)
    {
        var start = startDate.Text;
        var startTime = DateTime.Parse(start);
        var sqlStart = startTime.ToString("yyyy-MM-dd");

        var end = endDate.Text;
        var endTime = DateTime.Parse(end);
        var sqlEnd = endTime.ToString("yyyy-MM-dd");

        string sqlQuery = "SELECT TOP(100) TabID, TabName, Title, CreatedOnDate, TabPath From TableName " +
            "where CreatedOnDate >= " + sqlStart + " and CreatedOnDate <= " + sqlEnd +   " Order By TabName";

        BindDataToGridView(sqlQuery);
    }

    public void BindDataToGridView(string sqlQuery =
        "SELECT TOP(100) TabID, TabName, Title, CreatedOnDate, TabPath From TableName Order By TabName")
    {
        var connectionFromConfig = WebConfigurationManager.ConnectionStrings["ConnString"].ConnectionString;

        using (SqlConnection db = new SqlConnection(connectionFromConfig))
        {
            try
            {
                db.Open();
                SqlCommand command = new SqlCommand(sqlQuery, db);
                SqlDataAdapter dataAdapter = new SqlDataAdapter(command);
                DataSet dataSet = new DataSet();
                dataAdapter.Fill(dataSet);

                if (dataSet.Tables[0].Rows.Count > 0)
                {
                    dashboard.DataSource = dataSet;
                    dashboard.DataBind();
                }
            }
            catch (SqlException ex)
            {
                gridErrors.Text = ex.Message;
            }
            finally
            {
                db.Close();
                db.Dispose();
            }
        }
    }

OnPageIndexChanging 方法

protected void dashboard_PageIndexChanging(object sender, GridViewPageEventArgs e)
    {
        dashboard.PageIndex = e.NewPageIndex;
        BindDataToGridView();
    }

我需要在 Sql 服务器的 sqlStart 和 sqlEnd 变量前后添加单引号,以便将这些值与比较运算符一起使用。

好的,您找到了问题(缺少引号)。但是,归根结底? 是的,每个人都会蜂拥而至并注意“当”接受用户输入时,您不想连接到 sql(sql 注入的风险太高)。

但是,除非我们还为您提供了一个很好的设计方法,否则仅仅告诉您不要连接参数没有帮助。看看你的代码,你做了一个很棒的想法来拥有一个网格视图加载例程。而且您还想轻松地将 sql 传递给那个例程。然而,这个好主意 + 目标与使用强类型参数相冲突。

所以,让我们一箭双雕吧。

并发现使用参数通常是 LESS 代码,然后是一长串混乱的 sql 字符串,这很容易出错(这就是为什么你必须在这里 post)。

对于数字 - 没有引号,对于字符串 - 是,对于日期,也是。所以这是额外的开发人员工作量。那个又长又乱的字符串很难编写、调试和管理。

所以,我建议这个代码:

protected void Page_Load(object sender, EventArgs e)
{
        if (!Page.IsPostBack)
            BindDataToGridView();
}

void BindDataToGridView(SqlCommand cmdSQL = null)
{
    // default sql
    if (cmdSQL is null)
    {
        cmdSQL = new 
            SqlCommand("SELECT TabID, TabName, Title, CreatedOnDate, TabPath From TableName Order By TabName");
    }
        
    using (cmdSQL)
    {
        cmdSQL.Connection = new SqlConnection(conString);
        cmdSQL.Connection.Open();
        DataTable rst = new DataTable();            
        rst.Load(cmdSQL.ExecuteReader());
        dashboard.DataSource = rst;
        dashboard.DataBind();
    }
}

注意几件事: 我们不必创建单独的连接对象 - sqlcommand 有一个!! (并且由于我们没有创建单独的连接对象,因此处理 sql 命令会使用我们的 using 块来处理!!!

我们不需要单独的 datatable/dataset,也不需要数据适配器,我们也不需要 reader!! (sql 命令对象也有一个 reader!!!)。

所以,现在我们可以在没有参数的情况下调用我们的负载网格。

但是,对于当我们想要传递 sql 参数的情况?那么我们可以这样做:

{
    string sqlQuery 
      = "SELECT TabID, TabName, Title, CreatedOnDate, TabPath From TableName " +
        "WHERE CreatedOnDate >= @Start AND CreatedOnDate  <= @End ORDER By TabName";

    SqlCommand cmdSQL = new SqlCommand(sqlQuery);

    cmdSQL.Parameters.Add("@Start", SqlDbType.Date).Value = startDate.Text;
    cmdSQL.Parameters.Add("@End", SqlDbType.Date).Value = endDate.Text;

    BindDataToGridView(cmdSQL);
}

所以,其实我们可以有参数,我们可以有更少的代码。我们可以轻松阅读 SQL,我们可以将 cmd SQL 传递给那个例程。

因此,这不仅是建议不要连接字符串,而且通过正确的方法,我们不必这样做,我们可以获得强大的数据类型转换和更少的代码,甚至更少的代码错误机会。

此外,检查 sql 服务器列是否为日期或日期时间。如果是日期时间,则在查询参数中指定该数据类型。

此外,您可以放弃 TOP 子句 - 只有在创建理论上不支持排序输出的 SQL 视图时才需要它。但对于原始 sql,则可以删除 TOP 子句。