internal static void Execute(QuerySource[] sources, string queryText, IWriter writer, ParallelOptions options, bool dumpSql, Dictionary <string, object> parameters) { RowAccessor rowAccessor = null; var locker = new object(); var runTimestamp = DateTime.Now; var writeStarted = false; try { Parallel.ForEach(sources, options, (source, state) => { try { if (state.ShouldExitCurrentIteration) { return; } var sql = Translate(source, queryText, runTimestamp); if (dumpSql) { Console.Out.WriteLine("\r\n[{0}]\r\n{1}\r\n====>\r\n{2}", source.ConnectionString, queryText, sql); } if (state.ShouldExitCurrentIteration) { return; } var db = new PostgreeSqlDatabase(source.ConnectionString); db.Execute(sql, parameters, c => { if (state.ShouldExitCurrentIteration) { return; } using (var reader = (NpgsqlDataReader)c.ExecuteReader()) { if (state.ShouldExitCurrentIteration) { return; } var columns = DatabaseHelpers.GetColumns(reader); lock (locker) if (rowAccessor == null) { rowAccessor = new RowAccessor(columns); writer.BeginWrite(columns); writeStarted = true; } else { DatabaseHelpers.CheckColumnsAreEqual(rowAccessor.Columns, "original", columns, "current"); } if (state.ShouldExitCurrentIteration) { return; } while (reader.Read()) { if (state.ShouldExitCurrentIteration) { return; } lock (locker) { rowAccessor.Reader = reader; writer.Write(rowAccessor); } } } }); } catch (Exception e) { const string messageFormat = "error has occurred for database [{0}]"; throw new InvalidOperationException( string.Format(messageFormat, source.ConnectionString), e); } }); } finally { if (writeStarted) { writer.EndWrite(); } } }