/// <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); }
/// <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); }