/// <summary>
        /// Checks if column names and datatype are valid
        /// Does the mapping contain a row without a match (input column ids are compared) in the SSIS input column collection?
        /// If match is found: Are mappings input columm name and datatype equal to SSIS input column name and datatype?
        /// </summary>
        /// <param name="input">SSIS input</param>
        /// <param name="componentMetaData">SSIS component metadata</param>
        /// <returns>Are column names and datatypes valid?</returns>
        private bool AreColumnNamesAndDataTypesValid(IDTSInput100 input, IsagEvents events)
        {
            foreach (ColumnConfig config in this.ColumnConfigList)
            {
                if (config.HasInput)
                {
                    IDTSInputColumn100 inputColumn;

                    try
                    {
                        inputColumn = input.InputColumnCollection.GetObjectByID(config.InputColumnId);
                    }
                    catch (Exception)
                    {
                        events.Fire(IsagEvents.IsagEventType.Error, "The Mapping contains at least one column with a non existent, but assigned input column!");
                        return(false);
                    }

                    if (inputColumn.Name != config.InputColumnName || config.DataTypeInput != SqlCreator.GetSQLServerDataTypeFromInput(inputColumn, config.IsGeometryDataType))
                    {
                        events.Fire(IsagEvents.IsagEventType.Error, "The Mapping contains at least one column with a name or datatype differing from the assigned input column!");

                        return(false);
                    }
                }
            }

            return(true);
        }
        /// <summary>
        /// Checks if SCD configuration is correct and returns Isag events if problems are found
        /// </summary>
        /// <param name="events">Isag events</param>
        private void WarnIfScdIsNotValid(IsagEvents events)
        {
            SCDList scdList = new SCDList(ColumnConfigList, DestinationTable);

            string message = "";

            if (!scdList.IsValid(ref message))
            {
                events.Fire(IsagEvents.IsagEventType.Warning, message);
            }

            bool isValid = true;

            foreach (ColumnConfig config in ColumnConfigList)
            {
                if (config.IsScdColumn && config.IsScdValidFrom)
                {
                    isValid = false;
                }
            }
            if (!isValid)
            {
                events.Fire(IsagEvents.IsagEventType.Warning, @"You have to choose ""SCD Column"" OR ""SCD ValidFrom"" for one column but not both!");
            }

            isValid = true;
            foreach (ColumnConfig config in ColumnConfigList)
            {
                if (string.IsNullOrEmpty(config.ScdTable) && (config.IsScdColumn || config.IsScdValidFrom))
                {
                    isValid = false;
                }
            }
            if (!isValid)
            {
                events.Fire(IsagEvents.IsagEventType.Warning, @"If choosing ""SCD Column"" or ""SCD ValidFrom"" you also have to fill out ""SCD Table"".");
            }

            isValid = true;
            foreach (ColumnConfig config in ColumnConfigList)
            {
                if (!string.IsNullOrEmpty(config.ScdTable) && !config.IsScdColumn && !config.IsScdValidFrom)
                {
                    isValid = false;
                }
            }
            if (!isValid)
            {
                events.Fire(IsagEvents.IsagEventType.Warning, @"If filling out ""SCD Table"" you have to choose ""SCD Column"" or ""SCD ValidFrom"".");
            }
        }
        /// <summary>
        /// Pre an dpost sql statements may contain placeholder for variables.
        /// Those placeholder will be replaced with variable values.
        /// </summary>
        /// <param name="templateStatement">sql statement</param>
        /// <returns>sql statement without placeholder</returns>
        public string GetExecuteStatementFromTemplate(string templateStatement)
        {
            string result  = templateStatement;
            string varName = "";

            try
            {
                if (result != "")
                {
                    while (result.Contains("@("))
                    {
                        IDTSVariables100 var = null;
                        int start            = result.IndexOf("@(", 0);
                        int end = result.IndexOf(")", start);

                        varName = result.Substring(start + 2, end - start - 2);

                        _variableDispenser.LockOneForRead(varName, ref var);

                        result = result.Replace("@(" + varName + ")", var[varName].Value.ToString());
                        var.Unlock();
                    }
                }
            }
            catch (Exception ex)
            {
                _events.Fire(IsagEvents.IsagEventType.ErrorVariableNotFound, "[{0}]: Variable not found: {1}",
                             new string[] { "Pre-/PostSql", ex.Message });
            }
            return(result);
        }
        /// <summary>
        /// Are all columns usage types set to readonly?
        /// </summary>
        /// <param name="vInputColumnCollection">SSIS virtual input column collection</param>
        /// <param name="componentMetaData">SSIS component metadata</param>
        /// <returns>Are all columns usage types set to readonly?</returns>
        private bool ContainsWrongUsageType(IDTSVirtualInputColumnCollection100 vInputColumnCollection, IsagEvents events)
        {
            for (int i = 0; i < vInputColumnCollection.Count; i++)
            {
                if (vInputColumnCollection[i].UsageType != DTSUsageType.UT_READONLY)
                {
                    events.Fire(IsagEvents.IsagEventType.Error, "The UsageType of all input columns has to be ReadOnly!");
                    return(true);
                }
            }

            return(false);
        }
        /// <summary>
        /// If update or insert is set, a destination column has to be set, too. Checks if condition is fullfilled.
        /// </summary>
        /// <param name="componentMetaData">SSIS component metadata</param>
        /// <returns>If update or insert is set, a destination column has to be set, too. Is condition is fullfilled?</returns>
        private bool ContainsColumnConfigWithoutOutput(IsagEvents events)
        {
            foreach (ColumnConfig config in ColumnConfigList)
            {
                if (!config.HasOutput && (config.Insert || config.Update))
                {
                    events.Fire(IsagEvents.IsagEventType.Error, @"If ""Use (insert)"" oder Use ""(Update)"" is choosen a destination columns has to be selected!");
                    return(true);
                }
            }

            return(false);
        }
        /// <summary>
        /// Does the SSIS input column collection contain an input column without a match in the oclumn configuration list?
        /// </summary>
        /// <param name="vInput">SSIS virtual input</param>
        /// <param name="componentMetaData">SSIS component metadata</param>
        /// <returns>Does the SSIS input column collection contain an input column without a match in the oclumn configuration list?</returns>
        private bool ContainsInputWithoutColumnConfig(IDTSVirtualInput100 vInput, IsagEvents events)
        {
            for (int i = 0; i < vInput.VirtualInputColumnCollection.Count; i++)
            {
                if (GetColumnConfigByInputColumnName(vInput.VirtualInputColumnCollection[i].Name) == null)
                {
                    events.Fire(IsagEvents.IsagEventType.Error, "The input contains at least one column that is not assigned to a column of the Mapping!");
                    return(true);
                }
            }

            return(false);
        }
        /// <summary>
        /// Does the mapping contian ia destination column, but insert or update is not marked?
        /// </summary>
        /// <param name="componentMetaData">SSIS component metadata</param>
        /// <returns>Does the mapping contian ia destination column, but insert or update is not marked?</returns>
        private bool ContainsUnusedColumns(IsagEvents events)
        {
            foreach (ColumnConfig config in ColumnConfigList)
            {
                if (config.HasOutput && (config.HasInput || config.HasFunction || config.HasDefault) && (!config.Insert && !config.Update) && !config.IsInputColumnUsed)
                {
                    events.Fire(IsagEvents.IsagEventType.Warning,
                                @"The Mapping contains a column with an output column and an input column, function or default value, but is not marked as ""Use (Insert)"" or ""Use (Update)""");
                    return(true);
                }
            }

            return(false);
        }
 /// <summary>
 /// If destination column is identity, neither insert nor update must be marked
 /// (exception: custom database command)
 /// </summary>
 /// <param name="componentMetaData">SSIS component metadata</param>
 /// <returns>If destination column is identity, neither insert nor update must be marked. Is condition fulfilled</returns>
 private bool InsertOrUpdateAutoIdColumn(IsagEvents events)
 {
     if (!UseCustomMergeCommand)
     {
         foreach (ColumnConfig config in ColumnConfigList)
         {
             if (config.IsOutputAutoId && (config.Insert || config.Update))
             {
                 events.Fire(IsagEvents.IsagEventType.Error, @"AutoID-Columns must not be marked as ""Use Insert"" or ""UseUpdate"".");
                 return(true);
             }
         }
     }
     return(false);
 }
Exemple #9
0
        /// <summary>
        /// Add a bulk copy thread
        /// </summary>
        /// <param name="tempTableName">temporary tablename</param>
        /// <param name="dt">Datatable (buffer with rows to write to the temporary table)</param>
        /// <param name="useTableLock">Use tablock?</param>
        public void AddBulkCopyThread(string tempTableName, DataTable dt, bool useTableLock)
        {
            //Logging.Log(IsagEvents.IsagEventType.BulkInsert, string.Format("DataTable {0} created with {1} rows.", (_createdBulkCopyThreads + 1).ToString(), dt.Rows.Count.ToString()));
            _status.AddStatus(_createdBulkCopyThreads + 1, dt.Rows.Count, Status.StatusType.dataTableCreated, IsagEvents.IsagEventType.Status);
            UpdateStatus();

            string         templateCreateTempTable = SqlCreator.GetCreateTempTable(_isagCustomProperties, Constants.TEMP_TABLE_PLACEHOLDER_BRACKETS);
            ThreadBulkCopy thread = new ThreadBulkCopy(_dbCmdThread, tempTableName, dt, templateCreateTempTable, _timeoutDb, _reattempts, (_createdBulkCopyThreads + 1).ToString(),
                                                       _cstr, _conn, useTableLock, _isagCustomProperties.UseBulkInsert);
            bool showWaitMessage = true;

            while (WaitForFreeBulkCopyThread())
            {
                if (showWaitMessage)
                {
                    _events.Fire(IsagEvents.IsagEventType.BulkInsert, "Waiting ... Max Threat Count for BulkCopys has been reached. " + DateTime.Now.ToString());
                }
                showWaitMessage = false;
                Thread.Sleep(180); //TODO: Timeout?
                UpdateStatus();
            }

            if (!showWaitMessage)
            {
                _events.Fire(IsagEvents.IsagEventType.BulkInsert, "Waiting for free Bulkcopy Thread finished. " + DateTime.Now.ToString());
            }

            if (!HasError())
            {
                _bulkCopyThreads.Add(thread);
                _createdBulkCopyThreads++;

                _status.AddStatus(_createdBulkCopyThreads, dt.Rows.Count, Status.StatusType.bulkCopyThreadCreated, IsagEvents.IsagEventType.Status);
                //Logging.Log(IsagEvents.IsagEventType.BulkInsert, string.Format("BulkCopy Thread {0} created [Datatable {1}: {2} rows]",
                //    _createdBulkCopyThreads.ToString(), _createdBulkCopyThreads.ToString(), dt.Rows.Count.ToString()));

                thread.Start();
                Logging.Log(IsagEvents.IsagEventType.BulkInsert, string.Format("BulkCopyThread Status: {0} finished, {1} created",
                                                                               _finishedBulkCopyThreads.ToString(), _createdBulkCopyThreads.ToString()));
            }
        }
        /// <summary>
        /// Checks if more that one key is selected and returns Isag events if problems are found
        /// </summary>
        /// <param name="events">Isag events</param>
        private void WarnIfMoreThanOneKeyIsSelected(IsagEvents events)
        {
            if (DbCommand == DbCommandType.Merge || DbCommand == DbCommandType.Merge2005)
            {
                int keys = 0;
                foreach (ColumnConfig config in ColumnConfigList)
                {
                    if (config.Key)
                    {
                        keys++;
                    }
                }

                if (keys > 1)
                {
                    events.Fire(IsagEvents.IsagEventType.Warning, "Es sind mehrere Keys ausgewählt.");
                }
            }
        }
        /// <summary>
        /// For database commands other "Bulk Insert" and "Insert", at least one column has to be marked as a key.
        /// </summary>
        /// <param name="componentMetaData">SSIS component metadata</param>
        /// <returns>For database commands other "Bulk Insert" and "Insert", at least one column has to be marked as a key. Is condition fulfilled?</returns>
        private bool IsKeyMissing(IsagEvents events)
        {
            if (DbCommand != DbCommandType.BulkInsert && DbCommand != DbCommandType.BulkInsertRowLock && DbCommand != DbCommandType.Insert)
            {
                foreach (ColumnConfig config in ColumnConfigList)
                {
                    if (config.Key)
                    {
                        return(false);
                    }
                }
            }
            else
            {
                return(false);
            }

            events.Fire(IsagEvents.IsagEventType.Error, @"No Key has been selected!");

            return(true);
        }
        /// <summary>
        /// Is an output column assigned to an input column twice?
        /// </summary>
        /// <param name="events">Isag events</param>
        /// <returns>Is an output column assigned to an input column twice?
        /// </returns>
        private bool ContainsDuplicateOutputColumn(IsagEvents events)
        {
            List <string> outputColumns = new List <string>();

            foreach (ColumnConfig config in ColumnConfigList)
            {
                if (config.OutputColumnName != "")
                {
                    if (outputColumns.Contains(config.OutputColumnName))
                    {
                        events.Fire(IsagEvents.IsagEventType.Error, "Please assign Outputcolumns only once.");
                        return(true);
                    }
                    else
                    {
                        outputColumns.Add(config.OutputColumnName);
                    }
                }
            }

            return(false);
        }
Exemple #13
0
        /// <summary>
        /// Executes the database command
        /// (data is written from temporary table to destination table)
        /// </summary>
        /// <param name="tempTableName">temporary table</param>
        public void ExecuteDbCommand(string tempTableName, int reattempts)
        {
            try
            {
                int rowsAffected = 0;

                IsagEvents.IsagEventType eventType = IsagEvents.IsagEventType.MergeBegin;
                string[] sqlTemplate = null;
                _dbCommand.GetDbCommandDefinition(out eventType, out sqlTemplate);

                if (sqlTemplate.Length > 0)
                {
                    string sql;

                    SqlCommand comm = _conn.CreateCommand();
                    comm.CommandTimeout = _IsagCustomProperties.TimeOutDb;
                    if (_dbTransaction != null)
                    {
                        comm.Transaction = _dbTransaction;
                    }
                    for (int i = 0; i < sqlTemplate.Length; i++)
                    {
                        sql = sqlTemplate[i].Replace(Constants.TEMP_TABLE_PLACEHOLDER_BRACKETS, tempTableName)
                              .Replace(Constants.TEMP_TABLE_PLACEHOLDER, tempTableName);

                        bool executeDbCommand = true;
                        int  attempt          = 1;
                        while (executeDbCommand)
                        {
                            try
                            {
                                comm.CommandText = sql;
                                rowsAffected     = comm.ExecuteNonQuery();

                                executeDbCommand = false;
                            }
                            catch (Exception ex)
                            {
                                if (!ex.Message.Contains("Timeout") || (attempt > reattempts && reattempts != 0))
                                {
                                    _events.FireError(new string[] { string.Format("DbCommand failed. [{0}]: {1}",
                                                                                   DateTime.Now.ToString(), sql) + ex.ToString() });

                                    throw ex;
                                }
                                else
                                {
                                    attempt++;
                                    _events.Fire(IsagEvents.IsagEventType.Sql,
                                                 string.Format("DbCommand: Timeout...trying again... [{0}]", DateTime.Now.ToString()));
                                }
                            }
                        }
                    }
                }

                _events.Fire(eventType, string.Format("[Exec DbCommand: {0}]: {1} rows were affected by the Sql Command. ({2})",
                                                      eventType.ToString(), rowsAffected.ToString(), DateTime.Now.ToString()));
            }

            catch (Exception ex)
            {
                _events.FireError(new string[] { string.Format("DbCommand failed. [{0}]",
                                                               DateTime.Now.ToString()) + ex.ToString() });
                throw;
            }
        }
        /// <summary>
        /// Connection managers are valid, if
        /// - main connection is set
        ///
        /// Sofern die externe Transaktion gewählt ist,
        /// If external transaction is used
        /// - bulk connection must be set
        /// - main connection must be able to access tthe temporary table created with the bulk connection
        /// - main connection and bulk connection must not be the same connections
        /// </summary>
        /// <param name="componentMetaData">SSIS component metadata</param>
        /// <returns>Are all connection managers valid?</returns>
        private bool AreConnectionManagersValid(IDTSComponentMetaData100 componentMetaData, IsagEvents events)
        {
            IDTSRuntimeConnection100 runtimeConn = null;
            SqlConnection            mainConn    = null;
            SqlConnection            bulkConn    = null;

            //Main
            try
            {
                runtimeConn = componentMetaData.RuntimeConnectionCollection[Constants.CONNECTION_MANAGER_NAME_MAIN];
            }
            catch (Exception) { }

            if (runtimeConn == null || runtimeConn.ConnectionManager == null)
            {
                events.Fire(IsagEvents.IsagEventType.Error, "ADO.NET [Main] DB Connection Manager has not been initialized.");
                return(false);
            }
            else
            {
                object tempConn = componentMetaData.RuntimeConnectionCollection[Constants.CONNECTION_MANAGER_NAME_MAIN].ConnectionManager.AcquireConnection(null);

                if (tempConn is SqlConnection)
                {
                    mainConn = (SqlConnection)tempConn;
                }
                else
                {
                    events.Fire(IsagEvents.IsagEventType.Error, "Only ADO.NET SQL Server connections are supported for the ADO.NET [Main] Connection.");
                    return(false);
                }
            }

            runtimeConn = null;

            //Bulk
            if (!UseExternalTransaction && mainConn != null)
            {
                bulkConn = mainConn;
            }
            else
            {
                try
                {
                    runtimeConn = componentMetaData.RuntimeConnectionCollection[Constants.CONNECTION_MANAGER_NAME_BULK];
                }
                catch (Exception) { }

                if (runtimeConn == null || runtimeConn.ConnectionManager == null)
                {
                    events.Fire(IsagEvents.IsagEventType.Error, "ADO.NET [Bulk] Connection Manager has not been initialized.");
                    return(false);
                }
                else
                {
                    object tempConn = componentMetaData.RuntimeConnectionCollection[Constants.CONNECTION_MANAGER_NAME_BULK].ConnectionManager.AcquireConnection(null);

                    if (tempConn is SqlConnection)
                    {
                        bulkConn = (SqlConnection)tempConn;
                    }
                    else
                    {
                        events.Fire(IsagEvents.IsagEventType.Error, "Only ADO.NET SQL Server connections are supported for the ADO.NET [Bulk] Connection.");
                        return(false);
                    }
                }
            }


            //External Transaction
            if (mainConn != null && bulkConn != null && UseExternalTransaction)
            {
                string mainConnectionServer = mainConn.DataSource;
                string bulkConnectionServer = bulkConn.DataSource;

                if (mainConnectionServer.StartsWith("."))
                {
                    mainConnectionServer = "localhost" + mainConnectionServer.Substring(1);
                }
                if (bulkConnectionServer.StartsWith("."))
                {
                    bulkConnectionServer = "localhost" + bulkConnectionServer.Substring(1);
                }

                // Die Main Connection muss Zugriff auf die Temporäre Tabelle der Bulk Connection haben
                if (mainConnectionServer != bulkConnectionServer)
                {
                    events.Fire(IsagEvents.IsagEventType.Error, "Please make sure that the Main Connection can access the temporary table created with the bulk Connection");

                    return(false);
                }


                // Die Main - und Bulk Connection dürfen nicht identsich sein
                bool areConnectionsIdentic =
                    componentMetaData.RuntimeConnectionCollection[Constants.CONNECTION_MANAGER_NAME_MAIN].ConnectionManagerID ==
                    componentMetaData.RuntimeConnectionCollection[Constants.CONNECTION_MANAGER_NAME_BULK].ConnectionManagerID;

                if (areConnectionsIdentic)
                {
                    events.Fire(IsagEvents.IsagEventType.Error, "Please make sure that the Main- and the Bulk Connection are not identical.");

                    return(false);
                }
            }

            return(true);
        }