代码之家  ›  专栏  ›  技术社区  ›  SearchForKnowledge

如何在会话中保存SQL查询以供以后使用

  •  1
  • SearchForKnowledge  · 技术社区  · 10 年前

    我有一个函数,每当按下按钮或更改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了?

    2 回复  |  直到 10 年前
        1
  •  4
  •   Black Frog    10 年前

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

    你可以使用 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
  •  2
  •   Dennis R    10 年前

    以您当前的代码结构,您无法做到这一点 strMainQuery 具有不带 WHERE 子句,并且随着下拉值的更改 哪里 条款因此,不能在会话中存储结果集,因为每次下拉选择都会改变值。

    这是你能做的。

    1. 检索的所有记录 strMain查询 并且将结果存储在会话或某些其他状态管理中。所以你的 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();
      

    我确实看到你在打电话 Pull数据 在两者中 !Page.IsPostBack 以及 else 部分 PageLoad 这意味着该函数 Pull数据 将在页面上的任何其他控件触发回发时调用。而是添加一个 OnSelectedIndexChanged 事件,并调用 Pull数据 方法