首页 新闻 会员 周边 捐助

一个C# winform程序做的数据导入工具,怎么做进度条?

0
悬赏园豆:5 [已解决问题] 解决于 2017-08-16 10:28

程序里动态生成很多条insert 的 sql,怎么知道实时的进度来做一个进度条,显示在程序界面呢?

问题补充:

我是在程序里面动态生成很多条insert sql语句,并且这些sql是放在一起一次性批量插入到数据库中的,不是循环多次调用数据库。我想知道在批量插入到数据库的时候能否知道插入的实时进度,然后做这个进度条。

sdns的主页 sdns | 初学一级 | 园豆:1
提问于:2017-08-15 08:18
< >
分享
最佳答案
1

SQL 语句中可以加入print,结合下面这个例子,应该就是你要的答案了

http://blog.csdn.net/yenange/article/details/50517750

收获园豆:4
hahanonym | 小虾三级 |园豆:1460 | 2017-08-15 09:16

按你这个方法搞定了,非常感谢。

但要设置SqlConnection的FireInfoMessageEventOnUserErrors = true; 才能每print一次调用一次SqlInfoMessageEventHandler。还有就是加了个多线程实现进度条。

sdns | 园豆:1 (初学一级) | 2017-08-16 10:27
其他回答(4)
0

界面拖放一个进度条,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

          }

入流程序员 | 园豆:203 (菜鸟二级) | 2017-08-15 08:41

我自己的项目是这样实现的!!!

支持(0) 反对(0) 入流程序员 | 园豆:203 (菜鸟二级) | 2017-08-15 08:43

@快乐菜鸟: 多条sql是一次性批量插入的,比如10万条sql,能否知道实时进度?

支持(0) 反对(0) sdns | 园豆:1 (初学一级) | 2017-08-15 09:02

@快乐菜鸟: 比如插入1万条时进度条走一点2万条再走一点,这样。

支持(0) 反对(0) sdns | 园豆:1 (初学一级) | 2017-08-15 09:03

@sdns: this.progressBar1.Step = 1;,可以设置10或20或30

支持(0) 反对(0) 入流程序员 | 园豆:203 (菜鸟二级) | 2017-08-15 09:08

@快乐菜鸟: 可是是一次性批量插入。像这样

string sql=@"

  insert into ...

      insert into ...

      insert into ...

      ...

";比如一共10万个insert into

然后一次性调用SqlCommand cmd=New SqlCommand(conn,sql);

cmd.ExecuteNonQuery();

支持(0) 反对(0) sdns | 园豆:1 (初学一级) | 2017-08-15 09:11

@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数据
           }

支持(0) 反对(0) 入流程序员 | 园豆:203 (菜鸟二级) | 2017-08-15 09:11
0

默认就有进度条控件,你根据你当前insert的数量/总数量,就能拿到该显示多少进度了。

幻天芒 | 园豆:37207 (高人七级) | 2017-08-15 08:57

那你可以分批插入,比如每500条。。

支持(0) 反对(0) 幻天芒 | 园豆:37207 (高人七级) | 2017-08-15 09:03

@幻天芒: 500条调用一次数据库?

支持(0) 反对(0) sdns | 园豆:1 (初学一级) | 2017-08-15 09:13

@sdns: 思路给你了,自己要主动思考哈。

支持(0) 反对(0) 幻天芒 | 园豆:37207 (高人七级) | 2017-08-15 09:40
0

比如一共10万个insert into

然后一次性调用SqlCommand cmd=New SqlCommand(conn,sql);

cmd.ExecuteNonQuery();

这种情况属于心理学范畴(进度条就是心理学的),

假设1000条需要1秒,10万条需要100秒,但是分成100个1000条通常耗时是比100秒更多,比如说120秒。

但是用户不会呆呆的看着你的界面,像死了一样,无法动弹,也不知道何时结束。

 

具体执行,有两种方式,一种简单点,就是出个沙漏,翻过来覆过去,告诉你我在忙,请等待。

第二种就是进度条(不需要非常准确),99%软件的进度条都是不准确的。不要吐槽微软的进度条胡说八道,因为

他只是想告诉你大约10%,而不是准确10%,因为好多工作没法准确计量。

收获园豆:1
爱编程的大叔 | 园豆:30844 (高人七级) | 2017-08-15 09:50

我觉得也是没办法完全准确的,像数据库备份还原都是一直在转,没有实际的进度。

支持(0) 反对(0) sdns | 园豆:1 (初学一级) | 2017-08-15 09:52

@sdns: 所有如果你一次性才插入10万条,就只能用沙漏形式。

具体到数据库插入这件事上,还要具体分析。

1、一次性插入,对数据库服务器会不会有很大的负担,造成影响其他人其他业务。

2、用户是否在意无法知道结束时间。

3、时间是多长,10分钟,1小时,1天。

考虑不同的因素,来决定采取什么样的用户界面。并不是速度最快就是最好的代码。

支持(0) 反对(0) 爱编程的大叔 | 园豆:30844 (高人七级) | 2017-08-15 09:56

@爱编程的大叔: 有道理!

支持(0) 反对(0) sdns | 园豆:1 (初学一级) | 2017-08-15 09:58

@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;

});

支持(0) 反对(0) 爱编程的大叔 | 园豆:30844 (高人七级) | 2017-08-15 11:54

@爱编程的大叔: 100条访问一次数据库呗

支持(0) 反对(0) sdns | 园豆:1 (初学一级) | 2017-08-15 12:08

@sdns: 我的答案都不看下么?

一次性插入10万条,每一千条中间加一个print

通过sqlconnection的事件就能拿到进度了啊,实时显示,而且还是比较精准的进度。

支持(0) 反对(0) hahanonym | 园豆:1460 (小虾三级) | 2017-08-15 13:11

@hahanonym: 看了,但昨天没时间尝试,我今天试试。

支持(0) 反对(0) sdns | 园豆:1 (初学一级) | 2017-08-16 08:36
0

按已执行的insert语句计数来显示进度,不现实。因为你的insert成了一个批处理,数据库不会中途给你返回执行的进度。

所以,爱编程的大叔说得有道理。

评估一下,如果整体耗用的时间不超过十秒(20,30?),那就弄个沙漏就行了。

如果时间更长,考虑分批,比如100条insert作为一批。

或者干脆逐条insert ,这样进度能按你想要的实现。

西漠以西 | 园豆:1675 (小虾三级) | 2017-08-15 11:17

逐条insert 10万条 访问10万次数据库,这样不行吧。

支持(0) 反对(0) sdns | 园豆:1 (初学一级) | 2017-08-15 11:56
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册