Ejemplo n.º 1
0
        /// <summary>处理核心。数据抽取后,需要报告进度,以及写入Actor</summary>
        /// <param name="table">正在处理的数据表</param>
        /// <param name="row">进度</param>
        /// <param name="page">当前数据页</param>
        /// <param name="actor">处理数据Actor</param>
        /// <returns></returns>
        protected virtual Boolean OnProcess(IDataTable table, Int64 row, DbTable page, Actor actor)
        {
            // 进度报告
            OnPage?.Invoke(this, new PageEventArgs {
                Table = table, Row = row, Page = page
            });

            // 消费数据。克隆对象,避免被修改
            actor.Tell(page.Clone());

            return(true);
        }
Ejemplo n.º 2
0
        /// <summary>从数据流恢复数据</summary>
        /// <param name="stream">数据流</param>
        /// <param name="table">数据表</param>
        /// <param name="progress">进度回调,参数为已处理行数和当前页表</param>
        /// <returns></returns>
        public Int32 Restore(Stream stream, IDataTable table, Action <Int32, DbTable> progress = null)
        {
            var writeDb = new WriteDbActor
            {
                Table = table,
                Dal   = this,

                // 最多同时堆积数页
                BoundedCapacity = 4,
            };
            //writeDb.Start();

            var sw = Stopwatch.StartNew();

            // 二进制读写器
            var bn = new Binary
            {
                EncodeInt = true,
                Stream    = stream,
            };

            var dt = new DbTable();

            dt.ReadHeader(bn);
            WriteLog("恢复[{0}/{1}]开始,共[{2:n0}]行", table.Name, ConnName, dt.Total);

            // 输出日志
            var cs = dt.Columns;
            var ts = dt.Types;

            WriteLog("字段[{0}]:{1}", cs.Length, cs.Join());
            WriteLog("类型[{0}]:{1}", ts.Length, ts.Join(",", e => e.Name));

            var row      = 0;
            var pageSize = 10_000;
            var total    = 0;

            while (true)
            {
                // 读取数据
                var count = dt.ReadData(bn, Math.Min(dt.Total - row, pageSize));

                var rs = dt.Rows;
                if (rs == null || rs.Count == 0)
                {
                    break;
                }

                WriteLog("恢复[{0}/{1}]数据 {2:n0} + {3:n0}", table.Name, ConnName, row, rs.Count);

                // 进度报告
                progress?.Invoke(row, dt);

                // 批量写入数据库。克隆对象,避免被修改
                writeDb.Tell(dt.Clone());

                // 下一页
                total += count;
                if (count < pageSize)
                {
                    break;
                }
                row += pageSize;
            }

            // 通知写入完成
            writeDb.Stop(-1);

            sw.Stop();
            var ms = sw.Elapsed.TotalMilliseconds;

            WriteLog("恢复[{0}/{1}]完成,共[{2:n0}]行,耗时{3:n0}ms,速度{4:n0}tps", table.Name, ConnName, total, ms, total * 1000L / ms);

            // 返回总行数
            return(total);
        }