有关大数据量的操作
客户要求所有数据(万级)加载于Grid中显示(WINFORM),这势必导致数据库超时,服务器超时,UI失去响应等等问题
现在普遍的做法是:
分批次获取数据,异步逐批加载到UI
所以在这想问问各位高手高高手,有更好的解决方案吗?请先细看要点和要求再做回答,谢谢。
要点:万级数据量, 加载于一个Grid中,不能分页,要一页显示,就像Excel一样。
要求:适用性高,因为还有好多地方涉及到这种问题;性能要求不需要太高,因为主要针对的是防超时,其次让用户知道数据在一点点的显示给他看就行了。
[解决办法]
如果我做这个应用,我会添加一个时间控件,interval设置为100ms(视客户端与数据库服务器连接所需时间而定),在请求数据时,先将这个grid能一页显示的数据从服务器取得,同时启动时间控件,当时间控件每触发一次时从服务器获得一批数据添加到grid中去,直到数据全部取完.估计用户在100ms内也不可能点击滚动条去拉到下一页去,这样可以让用户知道数据在不断加载(通过滚动条的中间拉块的变小),并且不致于一次传输太多数据而使客户端表观上显示处于停滞状态.
[解决办法]
参考 滚动条事件
当滚动条向下滚动到屏幕底部的时候自动填充下一屏数据。
[解决办法]
using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Windows.Forms;namespace WindowsFormsApplication2{ public partial class Form1 : Form { System.Data.DataSet ds=new DataSet(); System.Data.SqlClient.SqlConnection conn = new System.Data.SqlClient.SqlConnection(); public Form1() { InitializeComponent(); Form1.CheckForIllegalCrossThreadCalls = false; } private void button1_Click(object sender, EventArgs e) { conn.ConnectionString = "server=.;uid=sa;pwd=sqltest;database=media"; conn.Open(); using (System.Data.SqlClient.SqlCommand command = conn.CreateCommand()) { command.CommandText = "select * from v_test"; using (System.Data.SqlClient.SqlDataAdapter adp = new System.Data.SqlClient.SqlDataAdapter(command)) { adp.FillSchema(ds, SchemaType.Source); } this.dataGridView1.DataSource = ds.Tables[0]; new System.Threading.Thread(new System.Threading.ThreadStart(Query)).Start(); } } void Query() { using (System.Data.SqlClient.SqlCommand command = conn.CreateCommand()) { command.CommandText = "select top 10000 * from v_test"; using (System.Data.SqlClient.SqlDataReader reader = command.ExecuteReader()) { while (reader.Read()) { object[] v=new object[reader.FieldCount]; reader.GetValues(v); ds.Tables[0].LoadDataRow(v, true); this.label1.Text = string.Format("{0}行",this.ds.Tables[0].Rows.Count); } } conn.Close(); } } }}
[解决办法]
那还是把树默认收起来吧,展开的时候再查询
[解决办法]
你要解决数据库超时的问题,说明这些数据肯定不能一次性的从数据库读取出来。那就肯定要分次读取了。
你需要根据实际情况考虑如何分次去读,是按固定记录量分开,还是根据上下级树型结构分。这于使用时候的需求有关
至于告诉用户正在进行处理,只需要有一个进度条就行了
做成多线程的,防止UI无相应
[解决办法]
那还是把树默认收起来吧,展开的时候再查询
[解决办法]
启动多个线程去取数据,每个线程取完数据的时候,UI刷新它那一块,相当于异步响应。每个线程取自己的那部分数据,这样用户体验好一些。
[解决办法]
怕超时的话由两方面入手,一是检查当前的查询SQL速度能否再提升,包括优化写法和增加索引。二是把读取动作分解,一次只读一部分,分多次读完。参考分页的读取方法,用子线程读取一部分填充一部分,这样就不会让用户等到所有数据加载完成才能看到了。
------解决方案--------------------
多线程取数据 默认取出树的根节点 子节点点击获取数据!