繁体   English   中英

批量C#数据表到Postgresql表

[英]Bulk C# datatable to postgresql table

我有一个包含数千条记录的数据表。 我有一个与数据表相同字段的postgres表。 我想每天截断该表并再次填充数据表的数据。 我已经看过sql批量复制,但是在postgres上不可用。 那么,哪种方法最有效?

  • 每条记录插入一个
  • 多次插入:插入表值(1,1),(1,2),(1,3),(2,1);
  • 从数据表中选择并使用linq插入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();
}

如其他答案中所述,没有内置的解决方案,只有一些帮助程序库(免费和非免费),我个人想出了自己的解决方案。 优点是

  • 免费,易于使用
  • 不需要额外的映射设置,它可以重用来自数据库本身和EF DbContext的元数据
  • 使用动态代码构建来提高性能

用法是这样的:

var uploader = new NpgsqlBulkUploader(context);
var data = GetALotOfData();
uploader.Insert(data);
// OR
uploader.Update(data);

我在那里描述了

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM