/// <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, }; var sw = Stopwatch.StartNew(); writeDb.Start(); // 二进制读写器 var bn = new Binary { EncodeInt = true, Stream = stream, }; var dt = new DbTable(); dt.ReadHeader(bn); 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 * 1000 / ms); // 返回总行数 return(total); }