NpgSqlCopyIn 推荐的错误处理
NpgSqlCopyIn recommended error handling
我有以下使用 .Net 代码中的 npgsql 进行 PostgreSQL 批量插入的代码。
try
{
var items = GetSourceData(task);
connection.Open();
var command = new NpgsqlCommand(null, connection);
BeforeDestinationCommandExecution(task, command);
command.CommandText = string.Format("COPY {0} FROM STDIN", task.DestinationTable);
command.CommandTimeout = 3600;
var cin = new NpgsqlCopyIn(command, connection);
var rowCount = 0;
try
{
cin.Start();
foreach (var item in items)
{
var b = StreamEncoding.GetBytes(ConvertSourceData(item));
cin.CopyStream.Write(b, 0, b.Length);
++rowCount;
}
cin.End();
log.Debug(string.Format("Table {0} contained {1:N0} records", task.DestinationTable, rowCount));
}
catch (Exception e)
{
log.ErrorException("Exception caught in inner try block - MigrateWithCopyMode", e);
try
{
// send CopyFail to server
cin.Cancel("Undo copy");
}
catch (Exception cancelException)
{
// we should get an error in response to our cancel request:
if (!cancelException.ToString().Contains("Undo copy"))
{
throw new Exception("Failed to cancel COPY: " + cancelException + " upon failure: " + e);
}
}
throw;
}
finally
{
_migrationCounts.Add(task.DestinationTable, rowCount);
}
最近 2 天,我在执行代码时遇到了未处理的异常。经过一些调查并将代码附加到 UnhandledException 事件。
System.AppDomain.CurrentDomain.UnhandledException += unhandledException;
我发现问题出在正在处理的数据上。
Error [16] [HubAdapterMsSqlPostgres] Unhandled exception Npgsql.NpgsqlException:
null value in column "name_ru" violates not-null constraint
Severity: ERROR
Code: 23502
at Npgsql.NpgsqlState.<ProcessBackendResponses_Ver_3>d__a.MoveNext()
at Npgsql.NpgsqlState.IterateThroughAllResponses(IEnumerable`1 ienum)
at Npgsql.NpgsqlConnector.NpgsqlContextHolder.ProcessServerMessages()
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
此错误是在不同的线程上生成的。我猜是在从前面的代码示例调用 cin.CopyStream.Write(b, 0, b.Length);
之后。
我的问题是
处理此类错误的推荐方法是什么,以便能够忽略具有错误值的行并继续批量插入操作
谢谢
您正在尝试导入包含与您的 table 定义不兼容的行的数据 - 它们缺少 non-nullable 列的数据。 COPY 是一个 all-or-nothing 过程:要么整个过程成功,要么完全失败。因此,您必须:
* 首先清理您的输入,删除有问题的行(这将涉及解析您的输入,这可能很困难),或者
* 暂时删除 table 上的 non-null 约束,执行复制,从 table 中删除有问题的行并恢复约束。这可能适合也可能不适合,具体取决于您的使用场景。
无论如何,您使用的是 Npgsql 2.x,它现在已经很旧且无人维护了。强烈建议您升级到最新版本的 Npgsql。
我有以下使用 .Net 代码中的 npgsql 进行 PostgreSQL 批量插入的代码。
try
{
var items = GetSourceData(task);
connection.Open();
var command = new NpgsqlCommand(null, connection);
BeforeDestinationCommandExecution(task, command);
command.CommandText = string.Format("COPY {0} FROM STDIN", task.DestinationTable);
command.CommandTimeout = 3600;
var cin = new NpgsqlCopyIn(command, connection);
var rowCount = 0;
try
{
cin.Start();
foreach (var item in items)
{
var b = StreamEncoding.GetBytes(ConvertSourceData(item));
cin.CopyStream.Write(b, 0, b.Length);
++rowCount;
}
cin.End();
log.Debug(string.Format("Table {0} contained {1:N0} records", task.DestinationTable, rowCount));
}
catch (Exception e)
{
log.ErrorException("Exception caught in inner try block - MigrateWithCopyMode", e);
try
{
// send CopyFail to server
cin.Cancel("Undo copy");
}
catch (Exception cancelException)
{
// we should get an error in response to our cancel request:
if (!cancelException.ToString().Contains("Undo copy"))
{
throw new Exception("Failed to cancel COPY: " + cancelException + " upon failure: " + e);
}
}
throw;
}
finally
{
_migrationCounts.Add(task.DestinationTable, rowCount);
}
最近 2 天,我在执行代码时遇到了未处理的异常。经过一些调查并将代码附加到 UnhandledException 事件。
System.AppDomain.CurrentDomain.UnhandledException += unhandledException;
我发现问题出在正在处理的数据上。
Error [16] [HubAdapterMsSqlPostgres] Unhandled exception Npgsql.NpgsqlException:
null value in column "name_ru" violates not-null constraint
Severity: ERROR
Code: 23502
at Npgsql.NpgsqlState.<ProcessBackendResponses_Ver_3>d__a.MoveNext()
at Npgsql.NpgsqlState.IterateThroughAllResponses(IEnumerable`1 ienum)
at Npgsql.NpgsqlConnector.NpgsqlContextHolder.ProcessServerMessages()
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
此错误是在不同的线程上生成的。我猜是在从前面的代码示例调用 cin.CopyStream.Write(b, 0, b.Length);
之后。
我的问题是
处理此类错误的推荐方法是什么,以便能够忽略具有错误值的行并继续批量插入操作
谢谢
您正在尝试导入包含与您的 table 定义不兼容的行的数据 - 它们缺少 non-nullable 列的数据。 COPY 是一个 all-or-nothing 过程:要么整个过程成功,要么完全失败。因此,您必须: * 首先清理您的输入,删除有问题的行(这将涉及解析您的输入,这可能很困难),或者 * 暂时删除 table 上的 non-null 约束,执行复制,从 table 中删除有问题的行并恢复约束。这可能适合也可能不适合,具体取决于您的使用场景。
无论如何,您使用的是 Npgsql 2.x,它现在已经很旧且无人维护了。强烈建议您升级到最新版本的 Npgsql。