public Response <ServiceBatchModel> AddBatch(ServiceBatchModel batch)
        {
            var repository = _unitOfWork.GetRepository <ServiceBatchModel>(SchemaName.Synch);

            SqlParameter        batchStatusIDParam = new SqlParameter("BatchStatusID", batch.BatchStatusID);
            SqlParameter        batchTypeIDParam   = new SqlParameter("BatchTypeID", batch.BatchTypeID);
            SqlParameter        batchConfigIDParam = new SqlParameter("ConfigID", batch.ConfigID);
            SqlParameter        batchUSNParam      = new SqlParameter("usn", batch.USN);
            SqlParameter        batchIsActiveParam = new SqlParameter("IsActive", batch.IsActive);
            SqlParameter        modifiedOnParam    = new SqlParameter("ModifiedOn", batch.ModifiedOn ?? DateTime.Now);
            List <SqlParameter> procParams         = new List <SqlParameter>()
            {
                batchStatusIDParam, batchTypeIDParam, batchConfigIDParam, batchUSNParam, batchIsActiveParam, modifiedOnParam
            };

            return(repository.ExecuteNQStoredProc("usp_AddBatch", procParams, idResult: true));
        }
        //public static void Sync(Object source, ElapsedEventArgs e)
        public static void Sync(int configID)
        {
            _debugMode        = ConfigurationManager.AppSettings["Debug"] != null && Convert.ToBoolean(ConfigurationManager.AppSettings["Debug"]);
            _debugLogFileMode = ConfigurationManager.AppSettings["DebugLogFile"] != null && Convert.ToBoolean(ConfigurationManager.AppSettings["DebugLogFile"]);

            // first lets get our current config, in case something has been updated
            var syncServ = new SynchronizationServiceDataProvider(_logger);
            var config   = syncServ.GetServiceConfiguration(configID).DataItems[0];


            // we only want to run this service is we have an active config for it
            // todo: the plan is at some point to have a network monitoring tool to set which configs are active, so services on multiple servers know if they should be running or not
            // NOTE: by having the services continue to check their configs, the configs can be changed
            if (_debugMode)
            {
                EventLog.WriteEntry("SynchronizationService", "Using the following ConfigXML: " + config.ConfigXML, EventLogEntryType.Information);
            }
            if (_debugLogFileMode)
            {
                using (StreamWriter sw = File.AppendText("Log.txt"))
                {
                    sw.WriteLine("Using the following ConfigXML: " + config.ConfigXML);
                }
            }

            if (config != null && config.IsActive != null && (bool)config.IsActive)
            {
                /*
                 * config.ConfigXML reads from the DB the configuration database containing
                 * SyncServer
                 *  - ProcessingServer
                 * Timer
                 *  - Interval
                 * LDAPServer
                 *  - LDAPPath
                 *  - LDAPUserFilter
                 *  - LDAPRoleFilter
                 *  - Name
                 *  - Port: Defaultvalue="389"
                 */
                using (XmlReader reader = XmlReader.Create(new StringReader(config.ConfigXML)))
                {
                    // create a directory identifier and connection,
                    reader.ReadToFollowing("SyncServer");
                    reader.ReadToDescendant("ProcessingServer");
                    reader.MoveToFirstAttribute();
                    var processingServer = reader.Value;

                    reader.ReadToFollowing("LDAPServer");
                    reader.ReadToDescendant("LDAPPath");
                    reader.MoveToFirstAttribute();
                    var ldapPath = reader.Value;
                    reader.ReadToFollowing("LDAPUserFilter");
                    reader.MoveToFirstAttribute();
                    var ldapUserFilterFromConfig = reader.Value;
                    reader.ReadToFollowing("LDAPRoleFilter");
                    reader.MoveToFirstAttribute();
                    var ldapRoleFilterFromConfig = reader.Value;

                    if (_debugMode)
                    {
                        EventLog.WriteEntry("SynchronizationService",
                                            "Sync Server host name should be " + System.Net.Dns.GetHostName() +
                                            ", ldap sync server configured is " + processingServer +
                                            ", ldap path configured is " + ldapPath +
                                            ", ldap user filter configured is " + ldapUserFilterFromConfig +
                                            ", ldap role filter from config is " + ldapRoleFilterFromConfig,
                                            EventLogEntryType.Information);
                    }

                    if (_debugLogFileMode)
                    {
                        using (StreamWriter sw = File.AppendText("Log.txt"))
                        {
                            sw.WriteLine("Sync Server host name should be " + System.Net.Dns.GetHostName() +
                                         ", ldap sync server configured is " + processingServer +
                                         ", ldap path configured is " + ldapPath +
                                         ", ldap user filter configured is " + ldapUserFilterFromConfig +
                                         ", ldap role filter from config is " + ldapRoleFilterFromConfig);
                        }
                    }
                    //Till here make sure that you have the right configuration on the right machine

                    // we need to look at the previous batch to know which updates to start requesting, as well as to make sure its completed before starting a new batch
                    var lastBatch = syncServ.GetLastBatch(config.ConfigID); // the batches are by config, not config type, as you can have more than 1 config for a given type
                    if (
                        processingServer == System.Net.Dns.GetHostName() &&

                        // we want to make sure we have the ldap info we need to pull what we need from AD
                        (
                            ldapPath != string.Empty && ldapUserFilterFromConfig != string.Empty && ldapRoleFilterFromConfig != string.Empty
                        )

                        &&

                        // only proceed w/ a new AD request, once the last request has been completed
                        (
                            lastBatch.DataItems.Count < 1 ||
                            (lastBatch.DataItems[0] != null && lastBatch.DataItems[0].BatchStatusID >= (int)BatchStatus.Completed)
                        )
                        )
                    {
                        var usnChanged = (lastBatch.DataItems.Count > 0) ? lastBatch.DataItems[0].USN : 0;

                        var ldapUserFilter = ldapUserFilterFromConfig.Replace(_usnChangedToken, usnChanged.ToString());
                        if (_debugMode)
                        {
                            EventLog.WriteEntry("SynchronizationService", "Searching AD for users using ldap filter string: " + ldapUserFilter, EventLogEntryType.Information);
                        }
                        if (_debugLogFileMode)
                        {
                            using (StreamWriter sw = File.AppendText("Log.txt"))
                            {
                                sw.WriteLine("Searching AD for users using ldap filter string: " + ldapUserFilter);
                            }
                        }
                        var resultsUsers = SearchAD(ldapPath, ldapUserFilter);

                        var ldapRolesFilter = ldapRoleFilterFromConfig.Replace(_usnChangedToken, usnChanged.ToString());
                        if (_debugMode)
                        {
                            EventLog.WriteEntry("SynchronizationService", "Searching AD for roles using ldap filter string: " + ldapRolesFilter, EventLogEntryType.Information);
                        }
                        if (_debugLogFileMode)
                        {
                            using (StreamWriter sw = File.AppendText("Log.txt"))
                            {
                                sw.WriteLine("Searching AD for roles using ldap filter string: " + ldapRolesFilter);
                            }
                        }
                        var resultsRoles = SearchAD(ldapPath, ldapRolesFilter);

                        // we only want to create a new batch, if there are actually results to be processed
                        if ((resultsUsers != null && resultsRoles != null) && (resultsUsers.Count > 0 || resultsRoles.Count > 0))
                        {
                            // add this new request to the db
                            var batch = new ServiceBatchModel {
                                BatchStatusID = (int)BatchStatus.Requesting, BatchTypeID = (int)BatchType.ADSynService, ConfigID = config.ConfigID, USN = _lastUSN + 1, IsActive = true
                            };
                            batch.BatchID = syncServ.AddBatch(batch).ID;
                            if (_debugMode)
                            {
                                EventLog.WriteEntry("SynchronizationService", "Batch created, ID: " + batch.BatchID, EventLogEntryType.Information);
                            }
                            if (_debugLogFileMode)
                            {
                                using (StreamWriter sw = File.AppendText("Log.txt"))
                                {
                                    sw.WriteLine("Batch created, ID: " + batch.BatchID);
                                }
                            }

                            var dtUsers = BuildUsersDataTable(resultsUsers, batch.BatchID, ldapPath);
                            if (_debugMode)
                            {
                                EventLog.WriteEntry("SynchronizationService", "Inserting users into UserStage table.", EventLogEntryType.Information);
                            }
                            if (_debugLogFileMode)
                            {
                                using (StreamWriter sw = File.AppendText("Log.txt"))
                                {
                                    sw.WriteLine("Inserting users into UserStage table.");
                                }
                            }
                            syncServ.BulkInsert(dtUsers, UserStageTable, _debugMode, _debugLogFileMode);

                            var dtRoles = BuildRolesDataTable(resultsRoles, batch.BatchID);
                            if (_debugMode)
                            {
                                EventLog.WriteEntry("SynchronizationService", "Inserting roles into RoleStage table.", EventLogEntryType.Information);
                            }
                            if (_debugLogFileMode)
                            {
                                using (StreamWriter sw = File.AppendText("Log.txt"))
                                {
                                    sw.WriteLine("Inserting roles into RoleStage table.");
                                }
                            }
                            syncServ.BulkInsert(dtRoles, RoleStageTable, _debugMode, _debugLogFileMode);

                            // also, lets populate which groups the users belong to
                            var dtUserRoles = BuildUserRolesDataTable(resultsRoles, batch.BatchID, ldapPath);
                            if (_debugMode)
                            {
                                EventLog.WriteEntry("SynchronizationService", "Inserting user's roles into RoleStage table.", EventLogEntryType.Information);
                            }
                            if (_debugLogFileMode)
                            {
                                using (StreamWriter sw = File.AppendText("Log.txt"))
                                {
                                    sw.WriteLine("Inserting user's roles into RoleStage table.");
                                }
                            }
                            syncServ.BulkInsert(dtUserRoles, UserRoleStageTable, _debugMode, _debugLogFileMode);

                            // if we've added any staging data to be processed, update the batch created for this interval for keeping up w/ the data to be processed
                            // NOTE: adding +1 to the last usn, as we are doing a >= to filter by usn, so we don't want to get the last usn again, the next time we look for updates
                            batch.BatchStatusID = (int)BatchStatus.Completed;
                            batch.BatchTypeID   = (int)BatchType.ADSynService;
                            batch.USN           = _lastUSN + 1;
                            if (_debugMode)
                            {
                                EventLog.WriteEntry("SynchronizationService", "Updating batch to Pending status with USN " + batch.USN + ".", EventLogEntryType.Information);
                            }
                            if (_debugLogFileMode)
                            {
                                using (StreamWriter sw = File.AppendText("Log.txt"))
                                {
                                    sw.WriteLine("Updating batch to Pending status with USN " + batch.USN + ".");
                                }
                            }
                            syncServ.UpdateBatch(batch);
                        }
                    }
                }
            }
        }