[英]Bulk C# datatable to postgresql table
我有一个包含数千条记录的数据表。 我有一个与数据表相同字段的postgres表。 我想每天截断该表并再次填充数据表的数据。 我已经看过sql批量复制,但是在postgres上不可用。 那么,哪种方法最有效?
谢谢。
也许您可以检查一下我的其他答案,在其中我描述了为该问题创建的一个小助手,从而使使用另一个助手变得非常容易: https : //stackoverflow.com/a/46063313/6654362
编辑:我最近遇到类似的问题,但我们正在使用Postgresql。 我想使用有效的bulkinsert,事实证明这很困难。 我尚未在该数据库上找到任何合适的免费库来这样做。 我只找到了这个帮助程序: https ://bytefish.de/blog/postgresql_bulk_insert/也在Nuget上。 我编写了一个小型的映射器,该映射器可以像实体框架那样自动映射属性:
public static PostgreSQLCopyHelper<T> CreateHelper<T>(string schemaName, string tableName)
{
var helper = new PostgreSQLCopyHelper<T>(schemaName, "\"" + tableName + "\"");
var properties = typeof(T).GetProperties();
foreach(var prop in properties)
{
var type = prop.PropertyType;
if (Attribute.IsDefined(prop, typeof(KeyAttribute)))
continue;
switch (type)
{
case Type intType when intType == typeof(int) || intType == typeof(int?):
{
helper = helper.MapInteger("\"" + prop.Name + "\"", x => (int?)typeof(T).GetProperty(prop.Name).GetValue(x, null));
break;
}
case Type stringType when stringType == typeof(string):
{
helper = helper.MapText("\"" + prop.Name + "\"", x => (string)typeof(T).GetProperty(prop.Name).GetValue(x, null));
break;
}
case Type dateType when dateType == typeof(DateTime) || dateType == typeof(DateTime?):
{
helper = helper.MapTimeStamp("\"" + prop.Name + "\"", x => (DateTime?)typeof(T).GetProperty(prop.Name).GetValue(x, null));
break;
}
case Type decimalType when decimalType == typeof(decimal) || decimalType == typeof(decimal?):
{
helper = helper.MapMoney("\"" + prop.Name + "\"", x => (decimal?)typeof(T).GetProperty(prop.Name).GetValue(x, null));
break;
}
case Type doubleType when doubleType == typeof(double) || doubleType == typeof(double?):
{
helper = helper.MapDouble("\"" + prop.Name + "\"", x => (double?)typeof(T).GetProperty(prop.Name).GetValue(x, null));
break;
}
case Type floatType when floatType == typeof(float) || floatType == typeof(float?):
{
helper = helper.MapReal("\"" + prop.Name + "\"", x => (float?)typeof(T).GetProperty(prop.Name).GetValue(x, null));
break;
}
case Type guidType when guidType == typeof(Guid):
{
helper = helper.MapUUID("\"" + prop.Name + "\"", x => (Guid)typeof(T).GetProperty(prop.Name).GetValue(x, null));
break;
}
}
}
return helper;
}
我以以下方式使用它(我有一个实体叫做Undertaking):
var undertakingHelper = BulkMapper.CreateHelper<Model.Undertaking>("dbo", nameof(Model.Undertaking));
undertakingHelper.SaveAll(transaction.UnderlyingTransaction.Connection as Npgsql.NpgsqlConnection, undertakingsToAdd));
我展示了一个有关事务的示例,但是也可以通过从上下文中检索到的普通连接来完成。 undertakingsToAdd是普通实体记录的枚举,我想将其批量插入数据库。
经过数小时的研究和尝试后,我获得了该解决方案,正如您所期望的那样,它更快,最终易于使用且免费! 我真的建议您使用此解决方案,这不仅是因为上述原因,还因为它是我对Postgresql本身没有问题的唯一解决方案,许多其他解决方案都可以完美使用,例如与SqlServer一起使用。
有一些选项可以批量插入PostgreSQL。
例如,在我的库中,我正在使用SQL复制
COPY TableName (Column1, Column2, Column3) FROM STDIN BINARY
免责声明 :我是Bulk-Operations.NET项目的所有者
该库使执行任何类型的批量操作变得非常容易:
在包括PostgreSQL在内的多个数据库提供程序中
// Easy to use
var bulk = new BulkOperation(connection);
bulk.BulkInsert(dt);
bulk.BulkUpdate(dt);
bulk.BulkDelete(dt);
bulk.BulkMerge(dt);
PostgreSQL确实有一个大容量副本(实际上称为copy
),并且它具有.NET的不错的包装。 如果要加载, NpgsqlCopyIn
使用NpgsqlCopyIn
,如果要提取数据,则可以使用NpgsqlCopyOut.
您的问题在细节上有点含糊-我不知道您的数据表中的字段或有关您实际数据库的任何内容,因此以以下示例为例,说明如何使用C#/ PostgreSQL将数据批量插入表中:
NpgsqlCopyIn copy = new NpgsqlCopyIn("copy table1 from STDIN WITH NULL AS '' CSV;",
conn);
copy.Start();
NpgsqlCopySerializer cs = new NpgsqlCopySerializer(conn);
cs.Delimiter = ",";
foreach (var record in RecordList)
{
cs.AddString(record.UserId);
cs.AddInt32(record.Age);
cs.AddDateTime(record.HireDate);
cs.EndRow();
}
cs.Close();
copy.End();
-编辑8/27/2019-
Npgsql的结构已完全更改。 以下是使用二进制导入的上述示例的样板文件(也提供了文本):
using (var writer = conn.BeginBinaryImport(
"copy user_data.part_list from STDIN (FORMAT BINARY)"))
{
foreach (var record in RecordList)
{
writer.StartRow();
writer.Write(record.UserId);
writer.Write(record.Age, NpgsqlTypes.NpgsqlDbType.Integer);
writer.Write(record.HireDate, NpgsqlTypes.NpgsqlDbType.Date);
}
writer.Complete();
}
如其他答案中所述,没有内置的解决方案,只有一些帮助程序库(免费和非免费),我个人想出了自己的解决方案。 优点是
用法是这样的:
var uploader = new NpgsqlBulkUploader(context);
var data = GetALotOfData();
uploader.Insert(data);
// OR
uploader.Update(data);
我在那里描述了
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.