/// <summary> /// /// </summary> /// <param name="connection"></param> /// <param name="tableName"></param> /// <param name="mappings"></param> /// <param name="bulkCopyTimeout"></param> /// <param name="identityBehavior"></param> /// <param name="dbSetting"></param> /// <param name="cancellationToken"></param> /// <returns></returns> private static async Task <NpgsqlBinaryImporter> GetNpgsqlBinaryImporterAsync(NpgsqlConnection connection, string tableName, IEnumerable <NpgsqlBulkInsertMapItem> mappings, int?bulkCopyTimeout, BulkImportIdentityBehavior identityBehavior, IDbSetting dbSetting, CancellationToken cancellationToken = default) { var copyCommand = GetBinaryImportCopyCommand(tableName, mappings, identityBehavior, dbSetting); #if NET5_0 var importer = await connection.BeginBinaryImportAsync(copyCommand, cancellationToken); #else var importer = await Task.FromResult(connection.BeginBinaryImport(copyCommand)); #endif // Timeout if (bulkCopyTimeout.HasValue) { importer.Timeout = TimeSpan.FromSeconds(bulkCopyTimeout.Value); } // Return return(importer); }
public async Task LoadAsync(Tenant tenant, ISerializer serializer, NpgsqlConnection conn, IEnumerable <T> documents, CancellationToken cancellation) { using var writer = await conn.BeginBinaryImportAsync(MainLoaderSql (), cancellation).ConfigureAwait(false); foreach (var document in documents) { _storage.AssignIdentity(document, tenant.TenantId, tenant.Database); await writer.StartRowAsync(cancellation).ConfigureAwait(false); await LoadRowAsync(writer, document, tenant, serializer, cancellation).ConfigureAwait(false); } await writer.CompleteAsync(cancellation).ConfigureAwait(false); }
protected async Task InsertAsync <T>(DbContext context, Type type, IList <T> entities, TableInfo tableInfo, Action <decimal> progress, CancellationToken cancellationToken, bool isAsync) { NpgsqlConnection connection = tableInfo.NpgsqlConnection; bool closeConnectionInternally = false; if (connection == null) { (connection, closeConnectionInternally) = isAsync ? await OpenAndGetNpgsqlConnectionAsync(context, tableInfo.BulkConfig, cancellationToken).ConfigureAwait(false) : OpenAndGetNpgsqlConnection(context, tableInfo.BulkConfig); } try { string sqlCopy = SqlQueryBuilderPostgreSql.InsertIntoTable(tableInfo, tableInfo.InsertToTempTable ? OperationType.InsertOrUpdate : OperationType.Insert); using var writer = isAsync ? await connection.BeginBinaryImportAsync(sqlCopy, cancellationToken).ConfigureAwait(false) : connection.BeginBinaryImport(sqlCopy); var uniqueColumnName = tableInfo.PrimaryKeysPropertyColumnNameDict.Values.ToList().FirstOrDefault(); var doKeepIdentity = tableInfo.BulkConfig.SqlBulkCopyOptions == SqlBulkCopyOptions.KeepIdentity; var propertiesColumnDict = ((tableInfo.InsertToTempTable || doKeepIdentity) && tableInfo.IdentityColumnName == uniqueColumnName) ? tableInfo.PropertyColumnNamesDict : tableInfo.PropertyColumnNamesDict.Where(a => a.Value != tableInfo.IdentityColumnName); var propertiesNames = propertiesColumnDict.Select(a => a.Key).ToList(); var entitiesCopiedCount = 0; foreach (var entity in entities) { if (isAsync) { await writer.StartRowAsync(cancellationToken).ConfigureAwait(false); } else { writer.StartRow(); } foreach (var propertyName in propertiesNames) { if (tableInfo.DefaultValueProperties.Contains(propertyName) && !tableInfo.PrimaryKeysPropertyColumnNameDict.ContainsKey(propertyName)) { continue; } var propertyValue = tableInfo.FastPropertyDict.ContainsKey(propertyName) ? tableInfo.FastPropertyDict[propertyName].Get(entity) : null; var propertyColumnName = tableInfo.PropertyColumnNamesDict.ContainsKey(propertyName) ? tableInfo.PropertyColumnNamesDict[propertyName] : string.Empty; var columnType = tableInfo.ColumnNamesTypesDict[propertyColumnName]; // string is 'text' which works fine if (columnType.StartsWith("character")) // when MaxLength is defined: 'character(1)' or 'character varying' { columnType = "character"; // 'character' is like 'string' } else if (columnType.StartsWith("varchar")) { columnType = "varchar"; } else if (columnType.StartsWith("numeric")) { columnType = "numeric"; } var convertibleDict = tableInfo.ConvertibleColumnConverterDict; if (convertibleDict.ContainsKey(propertyColumnName) && convertibleDict[propertyColumnName].ModelClrType.IsEnum) { if (propertyValue != null) { var clrType = tableInfo.ConvertibleColumnConverterDict[propertyColumnName].ProviderClrType; if (clrType == typeof(byte)) // columnType == "smallint" { propertyValue = (byte)propertyValue; } if (clrType == typeof(short)) { propertyValue = (short)propertyValue; } if (clrType == typeof(Int32)) { propertyValue = (int)propertyValue; } if (clrType == typeof(Int64)) { propertyValue = (long)propertyValue; } if (clrType == typeof(string)) { propertyValue = propertyValue.ToString(); } } } if (isAsync) { await writer.WriteAsync(propertyValue, columnType, cancellationToken).ConfigureAwait(false); } else { writer.Write(propertyValue, columnType); } } entitiesCopiedCount++; if (progress != null && entitiesCopiedCount % tableInfo.BulkConfig.NotifyAfter == 0) { progress?.Invoke(ProgressHelper.GetProgress(entities.Count, entitiesCopiedCount)); } } if (isAsync) { await writer.CompleteAsync(cancellationToken).ConfigureAwait(false); } else { writer.Complete(); } } finally { if (closeConnectionInternally) { //connection.Close(); if (isAsync) { await connection.CloseAsync(); //await context.Database.CloseConnectionAsync().ConfigureAwait(false); } else { connection.Close(); //context.Database.CloseConnection(); } } } }