예제 #1
0
        protected override BulkCopyRowsCopied ProviderSpecificCopy <T>(
            ITable <T> table,
            BulkCopyOptions options,
            IEnumerable <T> source)
        {
            // database name is not a part of table FQN in oracle
            var serverName = options.ServerName ?? table.ServerName;

            if (table.DataContext is DataConnection dataConnection && _provider.Adapter.BulkCopy != null &&
                serverName == null)
            {
                var connection = _provider.TryGetProviderConnection(dataConnection.Connection, dataConnection.MappingSchema);

                if (connection != null)
                {
                    var ed      = dataConnection.MappingSchema.GetEntityDescriptor(typeof(T));
                    var columns = ed.Columns.Where(c => !c.SkipOnInsert || options.KeepIdentity == true && c.IsIdentity).ToList();
                    var sb      = _provider.CreateSqlBuilder(dataConnection.MappingSchema);

                    // ODP.NET doesn't bulk copy doesn't work if columns that require escaping:
                    // - if escaping applied, pre-flight validation fails as it performs uppercase comparison and quotes make it fail with
                    //   InvalidOperationException: Column mapping is invalid
                    // - if escaping not applied - if fails as expected on server, because it treats passed name as uppercased name
                    //   and gives "ORA-00904: "STRINGVALUE": invalid identifier" error
                    // That's quite common error in bulk copy implementation error by providers...
                    var supported = true;
                    foreach (var column in columns)
                    {
                        if (column.ColumnName != sb.ConvertInline(column.ColumnName, ConvertType.NameToQueryField))
                        {
                            // fallback to sql-based copy
                            // TODO: we should add support for by-ordinal column mapping to workaround it
                            supported = false;
                            break;
                        }
                    }

                    if (supported)
                    {
                        var rd     = new BulkCopyReader <T>(dataConnection, columns, source);
                        var sqlopt = OracleProviderAdapter.OracleBulkCopyOptions.Default;
                        var rc     = new BulkCopyRowsCopied();

                        var tableName  = sb.ConvertInline(options.TableName ?? table.TableName, ConvertType.NameToQueryTable);
                        var schemaName = options.SchemaName ?? table.SchemaName;
                        if (schemaName != null)
                        {
                            schemaName = sb.ConvertInline(schemaName, ConvertType.NameToSchema);
                        }

                        if (options.UseInternalTransaction == true)
                        {
                            sqlopt |= OracleProviderAdapter.OracleBulkCopyOptions.UseInternalTransaction;
                        }

                        using (var bc = _provider.Adapter.BulkCopy.Create(connection, sqlopt))
                        {
                            var notifyAfter = options.NotifyAfter == 0 && options.MaxBatchSize.HasValue
                                                        ? options.MaxBatchSize.Value
                                                        : options.NotifyAfter;

                            if (notifyAfter != 0 && options.RowsCopiedCallback != null)
                            {
                                bc.NotifyAfter = options.NotifyAfter;

                                bc.OracleRowsCopied += (sender, args) =>
                                {
                                    rc.RowsCopied = args.RowsCopied;
                                    options.RowsCopiedCallback(rc);
                                    if (rc.Abort)
                                    {
                                        args.Abort = true;
                                    }
                                };
                            }

                            if (options.MaxBatchSize.HasValue)
                            {
                                bc.BatchSize = options.MaxBatchSize.Value;
                            }

                            if (options.BulkCopyTimeout.HasValue)
                            {
                                bc.BulkCopyTimeout = options.BulkCopyTimeout.Value;
                            }
                            else if (Configuration.Data.BulkCopyUseConnectionCommandTimeout)
                            {
                                bc.BulkCopyTimeout = connection.ConnectionTimeout;
                            }

                            bc.DestinationTableName  = tableName;
                            bc.DestinationSchemaName = schemaName;

                            for (var i = 0; i < columns.Count; i++)
                            {
                                bc.ColumnMappings.Add(_provider.Adapter.BulkCopy.CreateColumnMapping(i, columns[i].ColumnName));
                            }

                            TraceAction(
                                dataConnection,
                                () => "INSERT BULK " + (schemaName == null ? tableName : schemaName + "." + tableName) + "(" + string.Join(", ", columns.Select(x => x.ColumnName)) + ")" + Environment.NewLine,
                                () => { bc.WriteToServer(rd); return(rd.Count); });
                        }

                        if (rc.RowsCopied != rd.Count)
                        {
                            rc.RowsCopied = rd.Count;

                            if (options.NotifyAfter != 0 && options.RowsCopiedCallback != null)
                            {
                                options.RowsCopiedCallback(rc);
                            }
                        }

                        return(rc);
                    }
                }
            }


            return(MultipleRowsCopy(table, options, source));
        }
예제 #2
0
        protected override BulkCopyRowsCopied ProviderSpecificCopy <T>(
            ITable <T> table,
            BulkCopyOptions options,
            IEnumerable <T> source)
        {
            if (table.DataContext is DataConnection dataConnection && dataConnection.Transaction == null && _provider.Adapter.BulkCopy != null)
            {
                var connection = _provider.TryGetProviderConnection(dataConnection.Connection, dataConnection.MappingSchema);

                if (connection != null)
                {
                    var ed        = dataConnection.MappingSchema.GetEntityDescriptor(typeof(T));
                    var columns   = ed.Columns.Where(c => !c.SkipOnInsert || options.KeepIdentity == true && c.IsIdentity).ToList();
                    var sb        = _provider.CreateSqlBuilder(dataConnection.MappingSchema);
                    var rd        = new BulkCopyReader <T>(dataConnection, columns, source);
                    var sqlopt    = OracleProviderAdapter.OracleBulkCopyOptions.Default;
                    var rc        = new BulkCopyRowsCopied();
                    var tableName = GetTableName(sb, options, table);

                    if (options.UseInternalTransaction == true)
                    {
                        sqlopt |= OracleProviderAdapter.OracleBulkCopyOptions.UseInternalTransaction;
                    }

                    using (var bc = _provider.Adapter.BulkCopy.Create(connection, sqlopt))
                    {
                        var notifyAfter = options.NotifyAfter == 0 && options.MaxBatchSize.HasValue
                                                        ? options.MaxBatchSize.Value
                                                        : options.NotifyAfter;

                        if (notifyAfter != 0 && options.RowsCopiedCallback != null)
                        {
                            bc.NotifyAfter = options.NotifyAfter;

                            bc.OracleRowsCopied += (sender, args) =>
                            {
                                rc.RowsCopied = args.RowsCopied;
                                options.RowsCopiedCallback(rc);
                                if (rc.Abort)
                                {
                                    args.Abort = true;
                                }
                            };
                        }

                        if (options.MaxBatchSize.HasValue)
                        {
                            bc.BatchSize = options.MaxBatchSize.Value;
                        }

                        if (options.BulkCopyTimeout.HasValue)
                        {
                            bc.BulkCopyTimeout = options.BulkCopyTimeout.Value;
                        }
                        else if (Configuration.Data.BulkCopyUseConnectionCommandTimeout)
                        {
                            bc.BulkCopyTimeout = connection.ConnectionTimeout;
                        }

                        bc.DestinationTableName = tableName;

                        for (var i = 0; i < columns.Count; i++)
                        {
                            bc.ColumnMappings.Add(_provider.Adapter.BulkCopy.CreateColumnMapping(i, columns[i].ColumnName));
                        }

                        TraceAction(
                            dataConnection,
                            () => "INSERT BULK " + tableName + "(" + string.Join(", ", columns.Select(x => x.ColumnName)) + Environment.NewLine,
                            () => { bc.WriteToServer(rd); return(rd.Count); });
                    }

                    if (rc.RowsCopied != rd.Count)
                    {
                        rc.RowsCopied = rd.Count;

                        if (options.NotifyAfter != 0 && options.RowsCopiedCallback != null)
                        {
                            options.RowsCopiedCallback(rc);
                        }
                    }

                    return(rc);
                }
            }


            return(MultipleRowsCopy(table, options, source));
        }
예제 #3
0
        protected override BulkCopyRowsCopied ProviderSpecificCopy <T>(
            [JetBrains.Annotations.NotNull] DataConnection dataConnection,
            BulkCopyOptions options,
            IEnumerable <T> source)
        {
            if (dataConnection == null)
            {
                throw new ArgumentNullException("dataConnection");
            }

            var sqlBuilder = _dataProvider.CreateSqlBuilder();
            var descriptor = dataConnection.MappingSchema.GetEntityDescriptor(typeof(T));
            var tableName  = GetTableName(sqlBuilder, descriptor);

            if (dataConnection.Transaction == null)
            {
                if (_bulkCopyCreator == null)
                {
                    var clientNamespace    = OracleTools.AssemblyName + ".Client.";
                    var bulkCopyType       = _connectionType.Assembly.GetType(clientNamespace + "OracleBulkCopy", false);
                    var bulkCopyOptionType = _connectionType.Assembly.GetType(clientNamespace + "OracleBulkCopyOptions", false);
                    var columnMappingType  = _connectionType.Assembly.GetType(clientNamespace + "OracleBulkCopyColumnMapping", false);

                    if (bulkCopyType != null)
                    {
                        _bulkCopyCreator      = CreateBulkCopyCreator(_connectionType, bulkCopyType, bulkCopyOptionType);
                        _columnMappingCreator = CreateColumnMappingCreator(columnMappingType);
                    }
                }

                if (_bulkCopyCreator != null)
                {
                    var columns = descriptor.Columns.Where(c => !c.SkipOnInsert).ToList();
                    var rd      = new BulkCopyReader(_dataProvider, columns, source);
                    var rc      = new BulkCopyRowsCopied();

                    var bcOptions = 0;                     // Default

                    if (options.UseInternalTransaction == true)
                    {
                        bcOptions |= 1;                                                             // UseInternalTransaction = 1,
                    }
                    using (var bc = _bulkCopyCreator(dataConnection.Connection, bcOptions))
                    {
                        dynamic dbc = bc;

                        var notifyAfter = options.NotifyAfter == 0 && options.MaxBatchSize.HasValue ?
                                          options.MaxBatchSize.Value : options.NotifyAfter;

                        if (notifyAfter != 0 && options.RowsCopiedCallback != null)
                        {
                            if (_bulkCopySubscriber == null)
                            {
                                _bulkCopySubscriber = CreateBulkCopySubscriber(bc, "OracleRowsCopied");
                            }

                            dbc.NotifyAfter = notifyAfter;

                            _bulkCopySubscriber(bc, arg =>
                            {
                                dynamic darg  = arg;
                                rc.RowsCopied = darg.RowsCopied;
                                options.RowsCopiedCallback(rc);
                                if (rc.Abort)
                                {
                                    darg.Abort = true;
                                }
                            });
                        }

                        if (options.MaxBatchSize.HasValue)
                        {
                            dbc.BatchSize = options.MaxBatchSize.Value;
                        }
                        if (options.BulkCopyTimeout.HasValue)
                        {
                            dbc.BulkCopyTimeout = options.BulkCopyTimeout.Value;
                        }

                        dbc.DestinationTableName = tableName;

                        for (var i = 0; i < columns.Count; i++)
                        {
                            dbc.ColumnMappings.Add((dynamic)_columnMappingCreator(i, columns[i].ColumnName));
                        }

                        dbc.WriteToServer(rd);
                    }

                    rc.RowsCopied = rd.Count;

                    return(rc);
                }
            }

            return(MultipleRowsCopy(dataConnection, options, source));
        }