2016-07-29 2 views
0

У меня есть datatable с тысячами записей. У меня есть стол postgres с теми же полями данных. Я хочу, чтобы каждый день обрезал эту таблицу и снова заполнял данные данных. Я видел объемный экземпляр sql, но он не доступен для postgres. Итак, какой из них наиболее эффективен?Bulk C# datatable to postgresql table

  • Одна вставка на каждую запись
  • Множественные вставки: вставить в таблице значений (1,1), (1,2), (1,3), (2,1);
  • Выберите из datatable и вставьте в postgres с linq? no idea ...

Спасибо.

+0

Почему бы не использовать материализованный вид, который вы обновляете каждый день? –

ответ

0

В PostgreSQL имеется опция опциональной вставки.

К примеру, в моей библиотеке, я использую SQL Copy

COPY TableName (Column1, Column2, Column3) FROM STDIN BINARY 

Отказ от ответственности: Я владелец проекта Bulk-Operations.NET

Эта библиотека делает его очень легко выполнять любые вид массовых операций:

  • BulkInsert
  • BulkUpdate
  • BulkDelete
  • BulkMerge

При множественном поставщике базы данных, включая PostgreSQL

// Easy to use 
var bulk = new BulkOperation(connection); 
bulk.BulkInsert(dt); 
bulk.BulkUpdate(dt); 
bulk.BulkDelete(dt); 
bulk.BulkMerge(dt); 
0

PostgreSQL определенно имеет объемную копию (это на самом деле называется copy), и он имеет приятную обертку для .СЕТЬ. Если вы загружаете, вы хотите использовать NpgsqlCopyIn, и если вы извлекаете данные, вы можете использовать NpgsqlCopyOut.

Ваш вопрос немного расплывчато по деталям - я не знаю полей в вашем datatable или что-нибудь о вашем текущая база данных, поэтому примите это как краткий пример о том, как основная часть данных вставки в таблицу, используя 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(); 
3

Возможно, вы можете проверить мой другой ответ, в котором я описываю немного помощника, я создал для этого проблема, использование другого помощника очень просто: https://stackoverflow.com/a/46063313/6654362

Редактировать: Я недавно столкнулся с подобной проблемой, но мы использовали Postgresql. Я хотел использовать эффективный bulkinsert, что оказалось довольно сложным. Я не нашел в этой БД надлежащей бесплатной библиотеки. Я только нашел этого помощника: https://bytefish.de/blog/postgresql_bulk_insert/ который также находится на Nuget.Я написал небольшой картографа, которая автоматически отображается окно свойств, как Entity Framework делает:

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)); 

я показал пример с транзакции, но это также можно сделать с обычным подключением, полученным из контекста. ПредпринимателиToAdd перечислены в нормальных записей сущностей, которые я хочу загрузить в базу данных.

Это решение, которое я получил после нескольких часов исследований и попыток, так же, как вы могли ожидать, намного быстрее и, наконец, легко использовать и бесплатно! Я действительно советую вам использовать это решение не только по причинам, упомянутым выше, но и потому, что это единственный, с которым у меня не было проблем с самим Postgresql, многие другие решения работают безупречно, например, с SqlServer.

0

Как сказано в других ответах, для этого нет встроенного решения и только некоторые вспомогательные библиотеки (бесплатные и несвободные), лично я придумываю собственное решение. Преимущества этого являются

  • Свободный, простой в использовании
  • Не требует дополнительной настройки для отображения, он повторно использует метаданные из самой БД и от EF DbContext
  • Использует dyamic здание код для выполнения

Реализуется это так:

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

Я описал его there