예제 #1
0
        public DB2iSeriesProviderAdapter(DB2iSeriesProviderType providerType)
        {
            adapter = providerType switch
            {
#if NETFRAMEWORK
                DB2iSeriesProviderType.AccessClient => DB2iSeriesAccessClientProviderAdapter.GetInstance(),
#endif
                DB2iSeriesProviderType.Odbc => OdbcProviderAdapter.GetInstance(),
                DB2iSeriesProviderType.OleDb => OleDbProviderAdapter.GetInstance(),
                DB2iSeriesProviderType.DB2 => DB2.DB2ProviderAdapter.GetInstance(),
                _ => throw ExceptionHelper.InvalidAdoProvider(providerType)
            };
            this.ProviderType = providerType;
        }
        private static MappingSchema GetMappingSchema(string configuration, DB2iSeriesProviderType providerType, bool mapGuidAsString)
        {
            var providerSchema = providerType switch
            {
#if NETFRAMEWORK
                DB2iSeriesProviderType.AccessClient => DB2iSeriesAccessClientProviderAdapter.GetInstance().MappingSchema,
#endif
                DB2iSeriesProviderType.DB2 => DB2.DB2ProviderAdapter.GetInstance().MappingSchema,
                _ => new MappingSchema()
            };

            return(mapGuidAsString
                                ? (MappingSchema) new DB2iSeriesGuidAsStringMappingSchema(configuration, providerSchema)
                                : new DB2iSeriesMappingSchema(configuration, providerSchema));
        }
예제 #3
0
        public static DB2iSeriesAccessClientProviderAdapter GetInstance()
        {
            if (_instance == null)
            {
                lock (_syncRoot)
                    if (_instance == null)
                    {
                        var assembly = Common.Tools.TryLoadAssembly(AssemblyName, ProviderFactoryName);
                        if (assembly == null)
                        {
                            throw new InvalidOperationException($"Cannot load assembly {AssemblyName}");
                        }

                        var connectionType  = assembly.GetType($"{ClientNamespace}.iDB2Connection", true);
                        var parameterType   = assembly.GetType($"{ClientNamespace}.iDB2Parameter", true);
                        var dataReaderType  = assembly.GetType($"{ClientNamespace}.iDB2DataReader", true);
                        var transactionType = assembly.GetType($"{ClientNamespace}.iDB2Transaction", true);
                        var commandType     = assembly.GetType($"{ClientNamespace}.iDB2Command", true);
                        var dbType          = assembly.GetType($"{ClientNamespace}.iDB2DbType", true);

                        var mappingSchema = new MappingSchema();

                        var iDB2BigIntType         = loadType("iDB2BigInt", DataType.Int64);
                        var iDB2BinaryType         = loadType("iDB2Binary", DataType.Binary);
                        var iDB2BlobType           = loadType("iDB2Blob", DataType.Blob);
                        var iDB2CharType           = loadType("iDB2Char", DataType.Char);
                        var iDB2CharBitDataType    = loadType("iDB2CharBitData", DataType.Binary);
                        var iDB2ClobType           = loadType("iDB2Clob", DataType.Text);
                        var iDB2DataLinkType       = loadType("iDB2DataLink", DataType.NText);
                        var iDB2DateType           = loadType("iDB2Date", DataType.Date);
                        var iDB2DbClobType         = loadType("iDB2DbClob", DataType.NText);
                        var iDB2DecFloat16Type     = loadType("iDB2DecFloat16", DataType.Decimal);
                        var iDB2DecFloat34Type     = loadType("iDB2DecFloat34", DataType.Decimal);
                        var iDB2DecimalType        = loadType("iDB2Decimal", DataType.Decimal);
                        var iDB2DoubleType         = loadType("iDB2Double", DataType.Double);
                        var iDB2GraphicType        = loadType("iDB2Graphic", DataType.NChar);
                        var iDB2IntegerType        = loadType("iDB2Integer", DataType.Int32);
                        var iDB2NumericType        = loadType("iDB2Numeric", DataType.Decimal);
                        var iDB2RealType           = loadType("iDB2Real", DataType.Single);
                        var iDB2RowidType          = loadType("iDB2Rowid", DataType.VarBinary);
                        var iDB2SmallIntType       = loadType("iDB2SmallInt", DataType.Int16);
                        var iDB2TimeType           = loadType("iDB2Time", DataType.Time);
                        var iDB2TimeStampType      = loadType("iDB2TimeStamp", DataType.DateTime2);
                        var iDB2VarBinaryType      = loadType("iDB2VarBinary", DataType.VarBinary);
                        var iDB2VarCharType        = loadType("iDB2VarChar", DataType.VarChar);
                        var iDB2VarCharBitDataType = loadType("iDB2VarCharBitData", DataType.VarBinary);
                        var iDB2VarGraphicType     = loadType("iDB2VarGraphic", DataType.NVarChar);
                        var iDB2XmlType            = loadType("iDB2Xml", DataType.Xml);

                        var typeMapper = new TypeMapper();

                        typeMapper.RegisterTypeWrapper <iDB2Connection>(connectionType);
                        typeMapper.RegisterTypeWrapper <iDB2Parameter>(parameterType);
                        typeMapper.RegisterTypeWrapper <iDB2DbType>(dbType);

                        typeMapper.FinalizeMappings();

                        var dbTypeBuilder = typeMapper.Type <iDB2Parameter>().Member(p => p.iDB2DbType);
                        var typeSetter    = dbTypeBuilder.BuildSetter <IDbDataParameter>();
                        var typeGetter    = dbTypeBuilder.BuildGetter <IDbDataParameter>();

                        _instance = new DB2iSeriesAccessClientProviderAdapter(
                            connectionType,
                            dataReaderType,
                            parameterType,
                            commandType,
                            transactionType,

                            iDB2BigIntType,
                            iDB2BinaryType,
                            iDB2BlobType,
                            iDB2CharType,
                            iDB2CharBitDataType,
                            iDB2ClobType,
                            iDB2DataLinkType,
                            iDB2DateType,
                            iDB2DbClobType,
                            iDB2DecFloat16Type,
                            iDB2DecFloat34Type,
                            iDB2DecimalType,
                            iDB2DoubleType,
                            iDB2GraphicType,
                            iDB2IntegerType,
                            iDB2NumericType,
                            iDB2RealType,
                            iDB2RowidType,
                            iDB2SmallIntType,
                            iDB2TimeType,
                            iDB2TimeStampType,
                            iDB2VarBinaryType,
                            iDB2VarCharType,
                            iDB2VarCharBitDataType,
                            iDB2VarGraphicType,
                            iDB2XmlType,

                            mappingSchema,

                            typeSetter,
                            typeGetter,
                            typeMapper.BuildWrappedFactory((string connectionString) => new iDB2Connection(connectionString)),
                            typeMapper.BuildFunc <IDbConnection, string>(typeMapper.MapLambda((iDB2Connection conn) => conn.LibraryList)),
                            typeMapper.BuildFunc <IDbConnection, iDB2NamingConvention>(typeMapper.MapLambda((iDB2Connection conn) => conn.Naming)),

                            buildActionInvoker(commandType, "DeriveParameters"),
                            buildActionInvoker(commandType, "AddBatch")
                            );

                        DataConnection.WriteTraceLine(assembly.FullName, nameof(DB2iSeriesAccessClientProviderAdapter), System.Diagnostics.TraceLevel.Info);
        private BulkCopyRowsCopied ProviderSpecificCopyImpl_AccessClient <T>(
            ITable <T> table,
            BulkCopyOptions options,
            IEnumerable <T> source,
            DataConnection dataConnection,
            IDbConnection connection,
            DB2iSeriesAccessClientProviderAdapter adapter,
            Action <DataConnection, Func <string>, Func <int> > traceAction)
        {
            var descriptor = dataConnection.MappingSchema.GetEntityDescriptor(typeof(T));
            var columns    = descriptor.Columns.Where(c => !c.SkipOnInsert || options.KeepIdentity == true && c.IsIdentity).ToList();
            var rd         = new BulkCopyReader <T>(dataConnection, columns, source);
            var rc         = new BulkCopyRowsCopied();
            var sqlBuilder = dataConnection.DataProvider.CreateSqlBuilder(dataConnection.MappingSchema);
            var tableName  = GetTableName(sqlBuilder, options, table);

            var columnNames = columns.Select(x => x.ColumnName);
            var fields      = string.Join(", ", columnNames);
            var parameters  = string.Join(", ", columnNames.Select(x => "@" + x));

            var sql = $"INSERT INTO {tableName} ({fields}) VALUES({parameters})";

            var batchSize = Math.Min(options.MaxBatchSize ?? MAX_ACCESS_CLIENT_BATCH_SIZE, MAX_ACCESS_CLIENT_BATCH_SIZE);
            var sw        = Stopwatch.StartNew();

            using (var cmd = connection.CreateCommand())
            {
                cmd.CommandText = sql;
                adapter.DeriveParameters(cmd);

                var columnDataTypes = cmd.Parameters.Cast <IDbDataParameter>()
                                      .Select(adapter.GetDbType)
                                      .Select(adapter.GetDataType)
                                      .ToList();

                //*LOB and XML types not supported, fallback to multiple rows
                if (columnDataTypes.Any(x => x.In(DataType.Blob, DataType.Text, DataType.NText, DataType.Xml)))
                {
                    return(MultipleRowsCopy(table, options, source));
                }

                var columnDbDataTypes = columns
                                        .Select((x, i) => x
                                                .GetDbDataType(true)
                                                .WithDataType(columnDataTypes[i]))
                                        .ToList();

                var count = 0;
                var notificationBatchCount = 0;
                var bufferEmpty            = false;
                while (rd.Read())
                {
                    var i = 0;
                    bufferEmpty = false;
                    foreach (IDbDataParameter parameter in cmd.Parameters)
                    {
                        dataConnection.DataProvider.SetParameter(
                            dataConnection,
                            parameter,
                            columns[i].ColumnName,
                            columnDbDataTypes[i],
                            rd.GetValue(i++));
                    }

                    try
                    {
                        adapter.AddBatch(cmd);
                    }
                    //In case columns can't be mapped fall back to multiple rows
                    catch
                    {
                        return(MultipleRowsCopy(table, options, source));
                    }

                    count++;
                    notificationBatchCount++;

                    if (count % batchSize == 0)
                    {
                        execute();
                        if (rc.Abort)
                        {
                            return(rc);
                        }
                        bufferEmpty = true;
                    }
                }

                if (!bufferEmpty)
                {
                    execute();
                    if (rc.Abort)
                    {
                        return(rc);
                    }
                }

                void execute()
                {
                    cmd.ExecuteNonQuery();

                    rc.RowsCopied = count;

                    if (sw.Elapsed.TotalSeconds > options.BulkCopyTimeout)
                    {
                        traceAction(
                            dataConnection,
                            () => $"INSERT BULK {tableName} TIMEOUT AFTER {sw.Elapsed.TotalSeconds} SECONDS" + Environment.NewLine,
                            () => (int)rc.RowsCopied);

                        rc.Abort = true;

                        return;
                    }

                    if (options.NotifyAfter > 0 && notificationBatchCount > options.NotifyAfter)
                    {
                        options.RowsCopiedCallback?.Invoke(rc);
                        notificationBatchCount = 0;
                    }

                    if (rc.Abort)
                    {
                        traceAction(
                            dataConnection,
                            () => $"INSERT BULK {tableName} ABORTED BY USER" + Environment.NewLine,
                            () => (int)rc.RowsCopied);

                        return;
                    }
                }
            }

            return(rc);
        }