将DataTable bulk的整个值插入postgreSQL表

Kar*_*ngh 19 c# postgresql asp.net-mvc datatable

在SQL中,我们执行类似这样的操作来批量插入数据表

SqlBulkCopy copy = new SqlBulkCopy(sqlCon);
copy.DestinationTableName = strDestinationTable;            
copy.WriteToServer(dtFrom);

Blockquote
Run Code Online (Sandbox Code Playgroud)

但是在PostgreSQL中如何做这个操作

Pre*_*cco 7

使用参数简单插入

您的项目需要引用以下程序集:Npgsql.如果此引用在Visual Studio中不可见,则:

  1. 浏览到连接器的安装文件夹
  2. 执行: GACInstall.exe
  3. 重新启动Visual Studio.

样本表

CREATE TABLE "OrderHistory"
(
  "OrderId" bigint NOT NULL,
  "TotalAmount" bigint,
  CONSTRAINT "OrderIdPk" PRIMARY KEY ("OrderId")
)
WITH (
  OIDS=FALSE
);
ALTER TABLE "OrderHistory"
  OWNER TO postgres;
GRANT ALL ON TABLE "OrderHistory" TO postgres;
GRANT ALL ON TABLE "OrderHistory" TO public;
ALTER TABLE "OrderHistory" ALTER COLUMN "OrderId" SET (n_distinct=1);

GRANT SELECT("OrderId"), UPDATE("OrderId"), INSERT("OrderId"), REFERENCES("OrderId") ON "OrderHistory" TO public;
GRANT SELECT("TotalAmount"), UPDATE("TotalAmount"), INSERT("TotalAmount"), REFERENCES("TotalAmount") ON "OrderHistory" TO public;
Run Code Online (Sandbox Code Playgroud)

示例代码

请务必使用以下指令:

using Npgsql;
using NpgsqlTypes;
Run Code Online (Sandbox Code Playgroud)

在您的方法中输入以下源代码:

// Make sure that the user has the INSERT privilege for the OrderHistory table.
NpgsqlConnection connection = new NpgsqlConnection("PORT=5432;TIMEOUT=15;POOLING=True;MINPOOLSIZE=1;MAXPOOLSIZE=20;COMMANDTIMEOUT=20;COMPATIBLE=2.2.4.3;DATABASE=test;HOST=127.0.0.1;PASSWORD=test;USER ID=test");

connection.Open();

DataSet dataSet = new DataSet();

NpgsqlDataAdapter dataAdapter = new NpgsqlDataAdapter("select * from OrderHistory where OrderId=-1", connection);
dataAdapter.InsertCommand = new NpgsqlCommand("insert into OrderHistory(OrderId, TotalAmount) " +
                        " values (:a, :b)", connection);
dataAdapter.InsertCommand.Parameters.Add(new NpgsqlParameter("a", NpgsqlDbType.Bigint));
dataAdapter.InsertCommand.Parameters.Add(new NpgsqlParameter("b", NpgsqlDbType.Bigint));
dataAdapter.InsertCommand.Parameters[0].Direction = ParameterDirection.Input;
dataAdapter.InsertCommand.Parameters[1].Direction = ParameterDirection.Input;
dataAdapter.InsertCommand.Parameters[0].SourceColumn = "OrderId";
dataAdapter.InsertCommand.Parameters[1].SourceColumn = "TotalAmount";

dataAdapter.Fill(dataSet);

DataTable newOrders = dataSet.Tables[0];
DataRow newOrder = newOrders.NewRow();
newOrder["OrderId"] = 20;
newOrder["TotalAmount"] = 20.0;

newOrders.Rows.Add(newOrder);
DataSet ds2 = dataSet.GetChanges();
dataAdapter.Update(ds2);
dataSet.Merge(ds2);
dataSet.AcceptChanges();

connection.Close();
Run Code Online (Sandbox Code Playgroud)

关于绩效的思考

原始帖子未提及性能要求.有人要求解决方案必须:

  1. 插入使用 DataTable
  2. 不使用循环插入数据

如果您要插入大量数据,那么我建议您查看一下您的性能选项.在Postgres的文档建议您:

  • 禁用自动提交
  • 使用该COPY命令
  • 删除索引
  • 删除外键约束
  • 等等

有关优化Postgres插入的更多信息,请查看:

此外,还有许多其他因素会影响系统的性能.有关高级别的介绍,请查看:

其他选择

  • .NET连接器是否支持Postgres Copy命令?
    • 如果没有,你可以下载源代码Npgsql连接器,并添加自己的BulkCopy()方法.请务必先查看源代码的许可协议.
  • 检查Postgres是否支持表值参数.
    • 此方法允许您将表传入Postgres函数,然后可以将数据直接插入目标.
  • 从供应商处购买包含所需功能的Postgres .NET连接器.

其他参考文献


kom*_*ash 3

我前段时间也遇到过同样的问题。到目前为止,似乎还没有“现成可用”的解决方案。

我读过这篇文章并当时构建了一个类似的解决方案,直到今天它仍在有效使用。它基于从 STDIN 读取文件的文本查询。它使用 ADO.NET Postgre 数据提供程序Npgsql。您可以根据 DataTable 创建一个大字符串(或临时文件,导致内存使用),并使用 COPY 命令将该字符串用作文本查询。在我们的例子中,它比插入教导行快得多。

也许这不是一个完整的解决方案,但可能是一个很好的起点以及我所知道的一切。:)