程序里动态生成很多条insert 的 sql,怎么知道实时的进度来做一个进度条,显示在程序界面呢?
我是在程序里面动态生成很多条insert sql语句,并且这些sql是放在一起一次性批量插入到数据库中的,不是循环多次调用数据库。我想知道在批量插入到数据库的时候能否知道插入的实时进度,然后做这个进度条。
SQL 语句中可以加入print,结合下面这个例子,应该就是你要的答案了
按你这个方法搞定了,非常感谢。
但要设置SqlConnection的FireInfoMessageEventOnUserErrors = true; 才能每print一次调用一次SqlInfoMessageEventHandler。还有就是加了个多线程实现进度条。
界面拖放一个进度条,this.progressBar1.Visible = true;
this.progressBar1.Maximum = DSet.Tables[0].Rows.Count;
this.progressBar1.Minimum = 0;
this.progressBar1.Value = 1;
this.progressBar1.Step = 1;
for (int i = 0; i < DSet.Tables[0].Rows.Count; i++)
{
this.progressBar1.PerformStep();
INSERT INTO
}
我自己的项目是这样实现的!!!
@快乐菜鸟: 多条sql是一次性批量插入的,比如10万条sql,能否知道实时进度?
@快乐菜鸟: 比如插入1万条时进度条走一点2万条再走一点,这样。
@sdns: this.progressBar1.Step = 1;,可以设置10或20或30
@快乐菜鸟: 可是是一次性批量插入。像这样
string sql=@"
insert into ...
insert into ...
insert into ...
...
";比如一共10万个insert into
然后一次性调用SqlCommand cmd=New SqlCommand(conn,sql);
cmd.ExecuteNonQuery();
@sdns:
this.progressBar1.Visible = true;
this.progressBar1.Maximum = DSet.Tables[0].Rows.Count;
this.progressBar1.Minimum = 0;
this.progressBar1.Value = 1;
this.progressBar1.Step = 50;
for (int i = 0; i < DSet.Tables[0].Rows.Count; i++)
{
if(imod50==0)
{
this.progressBar1.PerformStep();
}
INSERT数据
}
默认就有进度条控件,你根据你当前insert的数量/总数量,就能拿到该显示多少进度了。
那你可以分批插入,比如每500条。。
@幻天芒: 500条调用一次数据库?
@sdns: 思路给你了,自己要主动思考哈。
比如一共10万个insert into
然后一次性调用SqlCommand cmd=New SqlCommand(conn,sql);
cmd.ExecuteNonQuery();
这种情况属于心理学范畴(进度条就是心理学的),
假设1000条需要1秒,10万条需要100秒,但是分成100个1000条通常耗时是比100秒更多,比如说120秒。
但是用户不会呆呆的看着你的界面,像死了一样,无法动弹,也不知道何时结束。
具体执行,有两种方式,一种简单点,就是出个沙漏,翻过来覆过去,告诉你我在忙,请等待。
第二种就是进度条(不需要非常准确),99%软件的进度条都是不准确的。不要吐槽微软的进度条胡说八道,因为
他只是想告诉你大约10%,而不是准确10%,因为好多工作没法准确计量。
我觉得也是没办法完全准确的,像数据库备份还原都是一直在转,没有实际的进度。
@sdns: 所有如果你一次性才插入10万条,就只能用沙漏形式。
具体到数据库插入这件事上,还要具体分析。
1、一次性插入,对数据库服务器会不会有很大的负担,造成影响其他人其他业务。
2、用户是否在意无法知道结束时间。
3、时间是多长,10分钟,1小时,1天。
考虑不同的因素,来决定采取什么样的用户界面。并不是速度最快就是最好的代码。
@爱编程的大叔: 有道理!
@sdns: 对于这种大量分批的执行,可以写一个帮助方法
public static IEnumerable<IEnumerable<T>> Batch<T>(this IEnumerable<T> source, int size) { List<T> batch = new List<T>(); foreach (var item in source) { batch.Add(item); if (batch.Count >= size) { yield return batch; batch.Clear(); } } if (batch.Count > 0) { yield return batch; } } public static void BatchAction<TSource>(this IEnumerable<TSource> source, int batchSize, Action<IEnumerable<TSource>> action) { foreach (var batch in source.Batch(batchSize)) { action(batch); } }
然后,需要的时候只需
sqlList.BatchAction(100, c=> () {
your code here for 100 rows sql;
});
@爱编程的大叔: 100条访问一次数据库呗
@sdns: 我的答案都不看下么?
一次性插入10万条,每一千条中间加一个print
通过sqlconnection的事件就能拿到进度了啊,实时显示,而且还是比较精准的进度。
@hahanonym: 看了,但昨天没时间尝试,我今天试试。
按已执行的insert语句计数来显示进度,不现实。因为你的insert成了一个批处理,数据库不会中途给你返回执行的进度。
所以,爱编程的大叔说得有道理。
评估一下,如果整体耗用的时间不超过十秒(20,30?),那就弄个沙漏就行了。
如果时间更长,考虑分批,比如100条insert作为一批。
或者干脆逐条insert ,这样进度能按你想要的实现。
逐条insert 10万条 访问10万次数据库,这样不行吧。