【问题标题】:How to save a SQL query in session to be used later如何在会话中保存 SQL 查询以供以后使用
【发布时间】:2014-08-14 18:52:27
【问题描述】:

我有一个函数,每次按下按钮或每次更改 7 个 DropDownList 选择中的任何一个时都会运行一个查询。如何更改现有方法以使用 Session 或 ViewState,以便我的页面将运行一次查询,然后针对 Session 或 ViewState 进行查询,而不是针对每个请求访问我的 SQL 服务器?

代码隐藏:

protected void Page_Load(object sender, EventArgs e)
{
    strMainQuery = @"SELECT  'http://dddfgdgdfg?objectid=' + CT.OBJECTID + '&classid=1224' 'Task Detail'
            ,LTRIM(RTRIM(CT.ATTR2846)) 'Service'
            ,LTRIM(RTRIM(CT.ATTR2812)) 'Status'
            ,CONVERT(VARCHAR(14), CT.ATTR2752, 110) 'Due Date'
            ,LTRIM(RTRIM(CT.ATTR2739)) 'Task Name'
            ,LTRIM(RTRIM(UA.REALNAME)) 'Owner'
            ,LTRIM(RTRIM(CT.ATTR2799)) 'Client'

        FROM HSI.RMOBJECTINSTANCE1224 CT INNER JOIN HSI.RMOBJECTINSTANCE1232 S ON CT.ATTR2846 = S.ATTR2821 INNER JOIN HSI.USERACCOUNT UA ON S.FK2852 = (UA.USERNUM * -1)";


    if (!Page.IsPostBack)
    {
        ViewState["sortOrder"] = "Asc";
        ViewState["sortExp"] = "Due Date";
        PullData("Due Date", "Asc"); //ASC: A (top) to Z (bottom) || # (low to high) || Date (oldest to newest)
    }
    else
    {
        PullData(ViewState["sortExp"].ToString(), ViewState["sortOrder"].ToString());
    }
}

public void PullData(string sortExp, string sortDir)
{
    string query = "";
    DataTable taskData = new DataTable();
    connString = ""; //connection string
    if (ddlTaskName.SelectedIndex > 0)
    {
        strClause += " AND CT.ATTR2739 = '" + ddlTaskName.SelectedItem.Text + "'";
    }
    else
    {
        strClause += " AND CT.ATTR2739 LIKE '%'";
    }
    if (ddlService.SelectedIndex > 0)
    {
        strClause += " AND CT.ATTR2846 = '" + ddlService.SelectedItem.Text + "'";
    }
    else
    {
        strClause += " AND CT.ATTR2846 LIKE '%'";
    }
    if (ddlStatus.SelectedIndex > 0)
    {
        strClause += " AND CT.ATTR2812 = '" + ddlStatus.SelectedItem.Text + "'";
    }
    else
    {
        strClause += " AND CT.ATTR2812 LIKE '%'";
    }
    if (ddlDueDate.SelectedIndex > 0)
    {
        strClause += " AND CONVERT(VARCHAR(14), CT.ATTR2752, 110) = '" + ddlDueDate.SelectedItem.Text + "'";
    }
    else
    {
        strClause += " AND CONVERT(VARCHAR(14), CT.ATTR2752, 110) LIKE '%'";
    }
    if (ddlOwner.SelectedIndex > 0)
    {
        strClause += " AND UA.REALNAME = '" + ddlOwner.SelectedItem.Text + "'";
    }
    else
    {
        strClause += " AND UA.REALNAME LIKE '%'";
    }
    if (ddlClient.SelectedIndex > 0)
    {
        strClause += " AND CT.ATTR2799 = '" + ddlClient.SelectedItem.Text + "'";
    }
    else
    {
        strClause += " AND CT.ATTR2799 LIKE '%'";
    }

    if (ddlTaskName.SelectedIndex == 0 && ddlService.SelectedIndex == 0 && ddlStatus.SelectedIndex == 0 && ddlDueDate.SelectedIndex == 0 && ddlOwner.SelectedIndex == 0 && ddlClient.SelectedIndex == 0)
    {
        query = strMainQuery + " WHERE CT.ACTIVESTATUS = 0";
    }
    else
    {
        query = strMainQuery + " WHERE CT.ACTIVESTATUS = 0" + strClause;
    }

    using (SqlConnection conn = new SqlConnection(connString))
    {
        try
        {
            SqlCommand cmd = new SqlCommand(query, conn);

            // create data adapter
            SqlDataAdapter da = new SqlDataAdapter(query, conn);
            // this will query your database and return the result to your datatable

            DataSet myDataSet = new DataSet();
            da.Fill(myDataSet);

            DataView myDataView = new DataView();
            myDataView = myDataSet.Tables[0].DefaultView;

            if (sortExp != string.Empty)
            {
                //MessageBox.Show(sortExp);
                //MessageBox.Show(sortDir);
                myDataView.Sort = string.Format("{0} {1}", sortExp, sortDir);
            }

            yourTasksGV.DataSource = myDataView;
            yourTasksGV.DataBind();

            TasksUpdatePanel.Update();

            conn.Close();
        }
        catch (Exception ex)
        {
            string error = ex.Message;
        }
    }
}

如您所见,每次调用 PullData 时,它都会输出到 SQL 服务器并运行查询,一旦我开始拥有越来越多的数据,最终会变慢。

如何将现有方法转换为查询一次并保存到 Session/ViewState,这样我就不必每次都查询 SQL Server?

【问题讨论】:

    标签: c# asp.net session viewstate


    【解决方案1】:

    在运行查询之前,请检查缓存。如果它在那里,请使用它。如果没有,请运行查询并将结果数据添加到缓存中。

    您可以使用Cache.Insert Method (String, Object, CacheDependency, DateTime, TimeSpan)。您可以找到一些很棒的缓存技巧:ASP.NET Caching: Techniques and Best Practices。

    以下是我将如何构建 PullData 方法:

    public void PullData(string sortExp, string sortDir)
    {
        // build your query string
        // ...
    
        // Now create a hash of that query string
        string cacheKey = HashHelper(query);
    
        DataSet ds = null;
    
        // check cache if key exists
        if(Cache[cacheKey] != null)
        {
             // read dataset from cache
             ds = (DataSet)Cache[cacheKey];
        }
        else
        {
            // perform sql command and fill your dataset
            // ....
            // save dataset to cache for 30 minutes or whatever you like
            Cache.Insert(cacheKey, ds, null, DateTime.Now.AddMinutes(30), TimeSpan.Zero);
        }
    
        // Get DataView based on sort options
        DataView myDataView = new DataView();
        myDataView = ds.Tables[0].DefaultView;
    
        if (sortExp != string.Empty)
        {
            myDataView.Sort = string.Format("{0} {1}", sortExp, sortDir);
        }
    
        yourTasksGV.DataSource = myDataView;
        yourTasksGV.DataBind();
    
        TasksUpdatePanel.Update();
    
        // keep calm and carry on
    }
    

    这是我的哈希助手

    private string HashHelper(string query)
    {
        using (SHA256Managed hashEngine = new SHA256Managed())
        {
            byte[] data = hashEngine.ComputeHash(Encoding.UTF8.GetBytes(query));
            StringBuilder hash = new StringBuilder(64);
            for (int i = 0; i < data.Length; i++)
            {
                hash.Append(data[i].ToString("x2"));
            }
            return hash.ToString();
        }
    
    }
    

    【讨论】:

    • 我去看看。谢谢。有没有例子?我可以使用并且类似于我已经在做的事情?
    • 哇...我没有看到编辑。谢谢你。我会在我的代码中尝试一下。
    • 我添加了它,到目前为止我的理解是有效的。谢谢你:)
    • 如果我更改查询,如何清除缓存?
    • 如果查询改变了它一个完全不同的哈希值。旧的查询/缓存数据会悄悄地消失。
    【解决方案2】:

    使用您当前的代码结构,您无法做到这一点。因为您的 strMainQuery 具有没有 WHERE 子句的 sql 语句,并且随着下拉值的更改,您正在动态构建 WHERE 子句的条件。因此,您不能将该结果集存储在会话中,因为每次下拉选择的值都会发生变化。

    这是你可以做的。

    1. 在没有任何 WHERE 条件的情况下检索 strMainQuery 的所有记录,并将结果存储在会话或其他一些状态管理中。所以你的PullData 方法将包含

      SqlCommand cmd = new SqlCommand(strMainQuery, conn);
      
    2. 随着下拉列表值的变化,访问会话对象并使用 LINQ 根据不同下拉列表的值过滤数据。这至少可以帮助您不要在每次下拉值更改时访问数据库服务器,而是

      获取一次 => 存储它 => 并使用 LINQ 进行额外的数据过滤

      在下面的行中绑定网格之前,请先进行数据过滤。

      // do the data filtering against the data source based on dropdown selected values
      yourTasksGV.DataSource = myDataView;
      yourTasksGV.DataBind();
      

    我确实看到您在!Page.IsPostBack 和else 部分都调用了PullData PageLoad,这意味着每次触发回发时都会调用此函数PullData页面上的任何其他控件。而是为下拉列表添加OnSelectedIndexChanged 事件并调用PullData 方法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-05-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-19
      • 2011-11-07
      相关资源
      最近更新 更多