示例#1
0
        /// <summary>
        /// Marks that the data load ended
        /// </summary>
        public void CloseAndMarkComplete()
        {
            lock (oLock)
            {
                //prevent double closing
                if (_isClosed)
                {
                    return;
                }

                _endTime = DateTime.Now;

                using (var con = _server.BeginNewTransactedConnection())
                {
                    try
                    {
                        DbCommand cmdUpdateToClosed =
                            _server.GetCommand("UPDATE DataLoadRun SET endTime=@endTime WHERE ID=@ID",
                                               con);

                        _server.AddParameterWithValueToCommand("@endTime", cmdUpdateToClosed, DateTime.Now);
                        _server.AddParameterWithValueToCommand("@ID", cmdUpdateToClosed, ID);

                        int rowsAffected = cmdUpdateToClosed.ExecuteNonQuery();

                        if (rowsAffected != 1)
                        {
                            throw new Exception(
                                      "Error closing off DataLoad in database, the update command resulted in " +
                                      rowsAffected + " rows being affected (expected 1) - will try to rollback");
                        }

                        con.ManagedTransaction.CommitAndCloseConnection();

                        _isClosed = true;
                    }
                    catch (Exception)
                    {
                        //if something goes wrong with the update, roll it back
                        con.ManagedTransaction.AbandonAndCloseConnection();

                        throw;
                    }

                    //once a record has been commited to the database it is redundant and no further attempts to read/change it should be made by anyone
                    foreach (TableLoadInfo t in this.TableLoads.Values)
                    {
                        //close any table loads that have not yet completed
                        if (!t.IsClosed)
                        {
                            t.CloseAndArchive();
                        }
                    }
                }
            }
        }
示例#2
0
        private void CheckLookupTableIsCorrectlyPopulated(ICheckNotifier notifier, string valueColumnName, string tableName, Dictionary <int, string> expected)
        {
            //see what is in the database
            var actual = new Dictionary <int, string>();

            using (var conn = _server.GetConnection())
            {
                conn.Open();

                var reader =
                    _server.GetCommand("SELECT ID, " + valueColumnName + " FROM " + tableName, conn).ExecuteReader();

                while (reader.Read())
                {
                    actual.Add(Convert.ToInt32(reader["ID"]), reader[valueColumnName].ToString().Trim());
                }

                reader.Close();
            }

            //now reconcile what is in the database with what we expect
            Dictionary <int, string> missing;
            Dictionary <int, string> collisions;
            List <string>            misnomers;

            ExpectedLookupsValuesArePresent(expected, actual, out missing, out collisions, out misnomers);

            if (!missing.Any() && !collisions.Any() && !misnomers.Any())
            {
                notifier.OnCheckPerformed(new CheckEventArgs(tableName + " contains the correct lookup values", CheckResult.Success, null));
                return;
            }

            //collisions cannot be resolved without manual intervention
            if (collisions.Any())
            {
                notifier.OnCheckPerformed(new CheckEventArgs(tableName + " there is a key collision between what we require and what is in the database, the mismatches are:" + Environment.NewLine +
                                                             collisions.Aggregate("", (s, n) => s + "Desired:(" + n.Key + ",'" + n.Value + "') VS Found:(" + n.Key + ",'" + actual[n.Key] + "')" + Environment.NewLine)
                                                             + collisions, CheckResult.Fail, null));
                return;
            }

            //misnomers cannot be resolved without manual intervention either
            if (misnomers.Any())
            {
                notifier.OnCheckPerformed(new CheckEventArgs(
                                              tableName + " the following ID conflicts were found:" +
                                              misnomers.Aggregate("", (s, n) => s + Environment.NewLine + n), CheckResult.Fail, null));
            }



            if (missing.Any())
            {
                //add missing values
                if (notifier.OnCheckPerformed(new CheckEventArgs(tableName + " does not contain all the required lookup statuses",
                                                                 CheckResult.Fail, null,
                                                                 "Insert the missing lookups (" + missing.Aggregate("", (s, pair) => s + ", " + pair.Value) + ")")))
                {
                    using (var c = _server.BeginNewTransactedConnection())
                    {
                        _server.GetCommand("SET IDENTITY_INSERT " + tableName + " ON ", c).ExecuteNonQuery();

                        foreach (var kvp in missing)
                        {
                            _server.GetCommand("INSERT INTO " + tableName + "(ID," + valueColumnName + ") VALUES (" + kvp.Key + ",'" + kvp.Value + "')", c).ExecuteNonQuery();
                        }

                        _server.GetCommand("SET IDENTITY_INSERT " + tableName + " OFF ", c).ExecuteNonQuery();

                        c.ManagedTransaction.CommitAndCloseConnection();
                    }
                }
            }
        }
        public DataTable ProcessPipelineData(DataTable toProcess, IDataLoadEventListener listener, GracefulCancellationToken cancellationToken)
        {
            if (toProcess == null)
            {
                return(null);
            }

            IDatabaseColumnRequestAdjuster adjuster = null;

            if (Adjuster != null)
            {
                var constructor = new ObjectConstructor();
                adjuster = (IDatabaseColumnRequestAdjuster)constructor.Construct(Adjuster);
            }

            //work out the table name for the table we are going to create
            if (TargetTableName == null)
            {
                if (string.IsNullOrWhiteSpace(toProcess.TableName))
                {
                    throw new Exception("Chunk did not have a TableName, did not know what to call the newly created table");
                }

                TargetTableName = QuerySyntaxHelper.MakeHeaderNameSane(toProcess.TableName);
            }

            ClearPrimaryKeyFromDataTableAndExplicitWriteTypes(toProcess);

            StartAuditIfExists(TargetTableName);

            if (_loggingDatabaseListener != null)
            {
                listener = new ForkDataLoadEventListener(listener, _loggingDatabaseListener);
            }

            EnsureTableHasDataInIt(toProcess);

            bool createdTable = false;

            if (_firstTime)
            {
                bool tableAlreadyExistsButEmpty = false;

                if (!_database.Exists())
                {
                    throw new Exception("Database " + _database + " does not exist");
                }

                discoveredTable = _database.ExpectTable(TargetTableName);

                //table already exists
                if (discoveredTable.Exists())
                {
                    tableAlreadyExistsButEmpty = true;

                    if (!AllowLoadingPopulatedTables)
                    {
                        if (discoveredTable.IsEmpty())
                        {
                            listener.OnNotify(this, new NotifyEventArgs(ProgressEventType.Warning, "Found table " + TargetTableName + " already, normally this would forbid you from loading it (data duplication / no primary key etc) but it is empty so we are happy to load it, it will not be created"));
                        }
                        else
                        {
                            throw new Exception("There is already a table called " + TargetTableName + " at the destination " + _database);
                        }
                    }

                    if (AllowResizingColumnsAtUploadTime)
                    {
                        _dataTypeDictionary = discoveredTable.DiscoverColumns().ToDictionary(k => k.GetRuntimeName(), v => v.GetDataTypeComputer(), StringComparer.CurrentCultureIgnoreCase);
                    }
                }
                else
                {
                    listener.OnNotify(this, new NotifyEventArgs(ProgressEventType.Information, "Determined that the table name " + TargetTableName + " is unique at destination " + _database));
                }

                //create connection to destination
                if (!tableAlreadyExistsButEmpty)
                {
                    createdTable = true;

                    if (AllowResizingColumnsAtUploadTime)
                    {
                        _database.CreateTable(out _dataTypeDictionary, TargetTableName, toProcess, ExplicitTypes.ToArray(), true, adjuster);
                    }
                    else
                    {
                        _database.CreateTable(TargetTableName, toProcess, ExplicitTypes.ToArray(), true, adjuster);
                    }

                    listener.OnNotify(this, new NotifyEventArgs(ProgressEventType.Information, "Created table " + TargetTableName + " successfully."));
                }

                _managedConnection = _server.BeginNewTransactedConnection();
                _bulkcopy          = discoveredTable.BeginBulkInsert(_managedConnection.ManagedTransaction);

                if (Culture != null)
                {
                    _bulkcopy.DateTimeDecider.Culture = Culture;
                }

                _firstTime = false;
            }

            try
            {
                if (AllowResizingColumnsAtUploadTime && !createdTable)
                {
                    ResizeColumnsIfRequired(toProcess, listener);
                }

                //push the data
                swTimeSpentWritting.Start();

                _affectedRows += _bulkcopy.Upload(toProcess);

                swTimeSpentWritting.Stop();
                listener.OnProgress(this, new ProgressEventArgs("Uploading to " + TargetTableName, new ProgressMeasurement(_affectedRows, ProgressType.Records), swTimeSpentWritting.Elapsed));
            }
            catch (Exception e)
            {
                _managedConnection.ManagedTransaction.AbandonAndCloseConnection();

                if (LoggingServer != null)
                {
                    _dataLoadInfo.LogFatalError(GetType().Name, ExceptionHelper.ExceptionToListOfInnerMessages(e, true));
                }

                throw new Exception("Failed to write rows (in transaction) to table " + TargetTableName, e);
            }

            return(null);
        }