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

            var pgconnection = (NpgsqlConnection)connection;

            using (var writer = pgconnection.BeginTextImport(String.Format(CultureInfo.InvariantCulture, "COPY {0} FROM STDIN WITH CSV", tableName)))
            {
                PostgreSQLInsightBulkCopy insightBulkCopy = new PostgreSQLInsightBulkCopy();

                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)
                        {
                            return;
                        }
                    }
                }

                // must call flush before end
                // cannot call close on the stream before end
                writer.Flush();
            }
        }
		/// <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;
			}
		}
        /// <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;
            }
        }