internal void OnRowsCopied(object sender, InsightRowsCopiedEventArgs e)
			{
				if (RowsCopied != null)
					RowsCopied(sender, e);
			}
		/// <summary>
		/// Bulk copies a set of objects to the server.
		/// </summary>
		/// <param name="connection">The connection to use.</param>
		/// <param name="tableName">The name of the table.</param>
		/// <param name="reader">The reader to read objects from.</param>
		/// <param name="configure">A callback method to configure the bulk copy object.</param>
		/// <param name="options">Options for initializing the bulk copy object.</param>
		/// <param name="transaction">An optional transaction to participate in.</param>
		public override void BulkCopy(IDbConnection connection, string tableName, IDataReader reader, Action<InsightBulkCopy> configure, InsightBulkCopyOptions options, IDbTransaction transaction)
		{
			if (reader == null) throw new ArgumentNullException("reader");

			NpgsqlCopyIn bulk = new NpgsqlCopyIn(String.Format(CultureInfo.InvariantCulture, "COPY {0} FROM STDIN WITH CSV", tableName), (NpgsqlConnection)connection);
			PostgreSQLInsightBulkCopy insightBulkCopy = new PostgreSQLInsightBulkCopy(bulk);

			try
			{
				bulk.Start();

				var stream = bulk.CopyStream;
				StreamWriter writer = new StreamWriter(stream);

				int row = 0;
				while (reader.Read())
				{
					for (int i = 0; i < reader.FieldCount; i++)
					{
						if (i > 0)
							writer.Write(CsvDelimiter);

						object value = reader.GetValue(i);

						if (value != DBNull.Value)
						{
							writer.Write(CsvQuote);
							writer.Write(_csvRegex.Replace(value.ToString(), CsvReplacement));
							writer.Write(CsvQuote);
						}
					}

					writer.WriteLine();

					row++;
					if (insightBulkCopy.NotifyAfter != 0 && row % insightBulkCopy.NotifyAfter == 0)
					{
						InsightRowsCopiedEventArgs e = new InsightRowsCopiedEventArgs();
						e.RowsCopied = row;
						insightBulkCopy.OnRowsCopied(insightBulkCopy, e);
						if (e.Abort)
						{
							bulk.Cancel("Cancelled");
							return;
						}
					}
				}

				// must call flush before end
				// cannot call close on the stream before end
				writer.Flush();
				bulk.End();
			}
			catch (Exception e)
			{
				bulk.Cancel(e.Message);

				throw;
			}
		}