上周末,帮朋友处理了一个关于大数据的查询与导出问题,整理一下,在此记录一下用以备忘,同时也为有类似需要的朋友提供一个参考.
背景:
改造步骤:
/// <summary> /// 响应查询按钮事件 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> PRivate void btnQuery_Click(object sender, EventArgs e) { if (txtCompany.Tag == null) { MessageBox.Show(this, "请选择指定的结算公司", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); return; } _pageIndex = 0; lblTotalCount.Text = "当前共[0]条数据"; gridData.Rows.Clear(); LoadQueryData(); } /// <summary> /// 开始查询数据 /// </summary> private void LoadQueryData() { plProcessStatus.Visible = true; //展示进度panel SetControlStatus(true); //设置其他功能控件暂时为只读状态 _isCurrentLoadEnd = false; //标识正在加载数据 bgwQuery.RunWorkerAsync(); //开始执行后台查询 }
/// <summary>/// 后台线程查询数据/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void bgwQuery_DoWork(object sender, DoWorkEventArgs e){ int total; _queryList = ExecQuery(_pageIndex, _pageSize, out total); _rowCount = total;}/// <summary>/// 执行分页查询方法,返回当前查询结果,/// </summary>/// <param name="pgIndex">当前页码</param>/// <param name="pgSize">每次查询分页大小</param>/// <param name="total">记录总数</param>/// <returns></returns>private List<OrderDetail> ExecQuery(int pgIndex, int pgSize, out int total){ List<OrderDetail> lst = null; var queryParam = BuildQueryExpression(pgIndex, pgSize); using (var services = new KYEService()) { lst = services.GetOrderDetailList(queryParam, out total); } return lst;}/// <summary>/// 构建查询条件/// </summary>/// <param name="pgIndex">当前查询第几页</param>/// <param name="pgSize">当前查询分页大小</param>/// <returns>当前查询条件</returns>private EFQueryParam<OrderDetail> BuildQueryExpression(int pgIndex, int pgSize){ //计算查询时间段 var queryBeginDate = new DateTime(_queryYear, _queryMonth, 1); var queryEndDate = queryBeginDate.AddMonths(1).AddDays(-1); //构建查询条件 var exp = QueryBuilder.Create<OrderDetail>(); exp = exp.Equals(t => t.PaymentCompanyId, (int)txtCompany.Tag);//结算公司 exp = exp.GreaterThanOrEqual(t => t.FromDate, queryBeginDate); //纳入月份转化为开始日期 exp = exp.LessThanOrEqual(t => t.FromDate, queryEndDate); //纳入月份沾化为结束日期 if (_queryPaymentType != EPaymentType.ALL) { exp = exp.Equals(t => t.PaymentType, _queryPaymentType); //付款方式 } //执行查询 var queryParam = new EFQueryParam<OrderDetail>(exp, "FromDate", true, pgIndex, pgSize); return queryParam;}/// <summary>/// 查询数据线程结束后,开始UI绑定数据/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void bgwQuery_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e){ plProcessStatus.Visible = false; //隐藏进度条 if (_queryList != null && _queryList.Count > 0) //当前查询有数据 { //后台线程异步展示数据到UI Thread thBindGrid = new Thread(() => { lblTotalCount.Invoke(new Action(() => { lblTotalCount.Text = string.Format("当前共[{0}]条数据", _rowCount); })); //循环绑定数据 for (int i = 0; i < _queryList.Count; i++) { gridData.Invoke(new Action<OrderDetail>(FillData), _queryList[i]); } _isCurrentLoadEnd = true; //标识当前查询加载结束 //绑定结束恢复其他功能按钮为可用状态(设置为非只读) btnExport.Invoke(new Action(() => { SetControlStatus(false); })); }); thBindGrid.IsBackground = true; thBindGrid.Start(); } else { SetControlStatus(false); }}
/// <summary>/// 绑定具体行数据/// </summary>/// <param name="detail">具体行数据</param>private void FillData(OrderDetail detail){ var index = gridData.Rows.Add(); gridData["dgcIndex", index].Value = index + 1; //TODO... 具体绑定到Grid的代码略}
/// <summary>/// 处理滚动条移动的时候,自动加载下一页数据/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void gridData_Scroll(object sender, ScrollEventArgs e){ //已经加载结束或者水平滚动,则不处理 if (!_isCurrentLoadEnd //当前查询数据还未绑定结束 || _rowCount <= gridData.Rows.Count //当前符合条件的数据已经查询完毕 || e.ScrollOrientation == ScrollOrientation.HorizontalScroll) { return; } var gridPageRowCount = gridData.DisplayRectangle.Height; //Grid每页能显示的记录数 //当前滚动到最后一页 if (gridData.FirstDisplayedScrollingRowIndex >= gridData.Rows.Count - gridPageRowCount - 1) { _pageIndex += 1; LoadQueryData(); //加载下一页数据 }}
/// <summary>/// 执行导出操作/// </summary>/// <param name="p"></param>private void ExecExport(string fileName){ plProcessStatus.Visible = true; SetControlStatus(true); IExport rpter = new ExcelExporter(); var formater = BuildExportFormater(); bool isQueryEnd = false; //当前是否查询结束 var templateFieName = Path.Combine(application.StartupPath, "Template", "Rpt_CustomerList.xls"); //创建供导出的队列 Queue<List<OrderDetail>> exportQueue = new Queue<List<OrderDetail>>(); #region 查询线程 //处理后台查询 Thread thQuery = new Thread(() => { int tempTotal = 0; int tempPgIndex = 0; int queryPageSize = 3000; //每次查询3k var tempList = ExecQuery(tempPgIndex, queryPageSize, out tempTotal); if (tempList != null && tempList.Count > 0) { lock (locker) { exportQueue.Enqueue(tempList); Monitor.PulseAll(locker); } tempPgIndex += 1; //循环查询直至查询结束 while (tempPgIndex * _pageSize < tempTotal) { var temp_tempList = ExecQuery(tempPgIndex, queryPageSize, out tempTotal); if (temp_tempList != null && temp_tempList.Count > 0) { lock (locker) { exportQueue.Enqueue(temp_tempList); //将查询结果加入到队列 Monitor.PulseAll(locker); } } tempPgIndex += 1; } } isQueryEnd = true; }); #endregion #region 导出excel线程 //处理将查询的结果写入到文件中 Thread th
新闻热点
疑难解答