/// <summary>
        /// Gets the insert case count.
        /// </summary>
        /// <param name="detail">The detail.</param>
        /// <param name="shortName">The short name.</param>
        /// <returns>the count</returns>
        public int GetInsertCaseCount(IConnectionDetail detail, IRulebaseConfiguration rule, int UKPRN)
        {
            Emitter.Publish(Indentation.FirstLevel, rule.InsertCount.Description);
            string command = rule.InsertCount.Command.Replace("{ukprn}", UKPRN.ToString());

            return(Coordinate.GetAtom <int>(command, detail));
        }
Beispiel #2
0
        /// <summary>
        /// Gets the candidates.
        /// </summary>
        /// <param name="forContext">For context.</param>
        /// <returns>
        /// returns a list of verified input data sources
        /// </returns>
        public async Task <IReadOnlyCollection <IInputDataSource> > GetCandidates(IConnectionDetail forContext)
        {
            // had to restrict the async operations here as some of the threads didn't appear to
            // be returning properly. this may be due to the expectation of failure when interrogating
            // some data sources.
            // i suppose it could be a bug in the oepration manager, brought on by the context switching
            // pondering...
            return(await Task.Run(() =>
            {
                var candidates = Collection.Empty <IInputDataSource>();
                var script = GetScript(BatchProcessName.GetInputSourceCandidates);

                var candidateNames = Context.GetList <string>(script, forContext);

                candidateNames.ForEach(candidate =>
                {
                    var response = Load(forContext, candidate);

                    if (response.IsSuccess())
                    {
                        candidates.Add(response.Payload);
                    }
                });

                return candidates.AsSafeReadOnlyList();
            }));
        }
Beispiel #3
0
 /// <summary>
 /// Loads...
 /// </summary>
 /// <param name="usingDetail">using detail.</param>
 /// <param name="withCandidate">with candidate.</param>
 /// <returns>
 /// an operational response that may contain an input data source
 /// (depends on the success of the check)
 /// </returns>
 public IOperationResponse <IInputDataSource> Load(IConnectionDetail usingDetail, string withCandidate)
 {
     // we expect this to fail as not all data sources will contain
     // collection detail information. an execption is not a problem
     // when it forms part of the control flow
     return(OperationManager.RunSafe(() => CheckCandidate(usingDetail, withCandidate)));
 }
Beispiel #4
0
        /// <summary>
        /// Gets the learner count.
        /// </summary>
        /// <param name="usingDetail">The using detail.</param>
        /// <param name="providerID">The provider identifier.</param>
        /// <returns>the learner count for this submission</returns>
        public int GetLearnerCount(IConnectionDetail usingDetail, int providerID)
        {
            var script = GetScript(BatchProcessName.GetLearnerCountForProvider, usingDetail.DBName);
            var temp   = Token.DoSecondaryPass(script, providerID);

            return(Context.GetAtom <int>(temp, usingDetail));
        }
        /// <summary>
        /// Gets the list.
        /// </summary>
        /// <typeparam name="TReturn">The type of the return.</typeparam>
        /// <param name="usingThisCommand">using this command.</param>
        /// <param name="inThisContext">in this context.</param>
        /// <returns>
        /// an list of type <typeparamref name="TReturn" />
        /// </returns>
        public ICollection <TReturn> GetList <TReturn>(string usingThisCommand, IConnectionDetail inThisContext)
        {
            It.IsEmpty(usingThisCommand)
            .AsGuard <ArgumentNullException>(nameof(usingThisCommand));
            It.IsNull(inThisContext)
            .AsGuard <ArgumentNullException>(nameof(inThisContext));

            return(UsingConnection(inThisContext, x =>
            {
                var tempList = Collection.Empty <TReturn>();
                using (var cmd = CreateCommand(usingThisCommand, x))
                {
                    using (var reader = cmd.ExecuteReader())
                    {
                        while (reader.Read())
                        {
                            var candidate = reader.GetValue(0);

                            tempList.Add(GetValue <TReturn>(candidate));
                        }
                    }
                }

                return tempList;
            }));
        }
Beispiel #6
0
        /// <summary>
        /// Checks the candidate.
        /// </summary>
        /// <param name="usingContext">using context.</param>
        /// <param name="withCandidate">with candidate.</param>
        /// <returns>
        /// an input data source on successful completion of the check
        /// </returns>
        public IInputDataSource CheckCandidate(IConnectionDetail usingDetail, string withCandidate)
        {
            var script   = GetScript(BatchProcessName.GetOperatingYear, withCandidate);
            var yearTemp = Context.GetAtom <string>(script, usingDetail);

            script = GetScript(BatchProcessName.GetCollectionType, withCandidate);
            var collectionTemp = Context.GetAtom <string>(script, usingDetail);

            script = GetScript(BatchProcessName.GetProviders, withCandidate);
            var providerIDs = Context.GetList <int>(script, usingDetail);

            var providers = Collection.Empty <ILearningProvider>();

            providerIDs.ForEach(x => providers.Add(new LearningProvider {
                ID = x
            }));

            return(new InputDataSource
            {
                Name = withCandidate,
                Container = usingDetail.Container,
                DBName = usingDetail.DBName,
                DBUser = usingDetail.DBUser,
                DBPassword = usingDetail.DBPassword,
                CollectionType = collectionTemp.AsOperationType(),
                OperatingYear = yearTemp.AsOperatingYear(),
                Providers = providers.AsSafeReadOnlyList()
            });
        }
Beispiel #7
0
        /// <summary>
        /// Exports to ILR
        /// </summary>
        /// <param name="usingSource">using source.</param>
        /// <param name="inContext">in context.</param>
        /// <param name="forProvider">for provider.</param>
        /// <returns>
        /// the currently running task
        /// </returns>
        public async Task Export(IInputDataSource usingSource, IConnectionDetail inContext, int forProvider)
        {
            It.IsNull(usingSource)
            .AsGuard <ArgumentNullException>(nameof(usingSource));
            It.IsNull(inContext)
            .AsGuard <ArgumentNullException>(nameof(inContext));

            await Task.Run(async() =>
            {
                using (Timing.BeginScope($"Export file for {forProvider}"))
                {
                    var schema       = Schemas.GetSchema(usingSource.OperatingYear);
                    var schemaPath   = Path.Combine(Location.OfAssets, schema.Message);
                    var templatePath = Path.Combine(Location.OfAssets, schema.BulkExport);
                    var candidate    = await FileManager.Load(templatePath);
                    var batch        = Batches.GetBatch(BatchProcessName.ExportSourceDataToILRFile, usingSource.OperatingYear);

                    candidate = candidate.Replace(Token.ForNamespace, schema.Namespace);

                    batch.Scripts
                    .ForEach(script => RunScript(script, inContext, forProvider, ref candidate));

                    var outputPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory), "exportILR.xml");
                    await FileManager.Save(outputPath, candidate);
                    await StripEmptyTags(outputPath);

                    Emitter.Publish(Indentation.FirstLevel, CommonLocalised.Completed);

                    //(!await Validator.IsValid(outputPath, schemaPath))
                    //    .AsGuard<OperationCanceledException, CommonLocalised>(CommonLocalised.SchemaValidationFailed);
                }
            });
        }
        /// <summary>
        /// Runs...
        /// </summary>
        /// <param name="thisBatchFile">this batch file.</param>
        /// <param name="inThisContext">The in this context.</param>
        /// <param name="withSupplementaryTokenReplacements">with supplementary token replacements.</param>
        public void Run(
            ISQLBatchScript thisBatchScript,
            IConnectionDetail inThisContext,
            Func <string, string> withSupplementaryTokenReplacements)
        {
            It.IsNull(thisBatchScript)
            .AsGuard <ArgumentNullException>(nameof(thisBatchScript));
            It.IsNull(inThisContext)
            .AsGuard <ArgumentNullException>(nameof(inThisContext));

            if (It.IsInRange(thisBatchScript.Type, TypeOfBatchScript.Ignored))
            {
                return;
            }

            Emitter.Publish(Indentation.FirstLevel, $"Running: '{thisBatchScript.Description}'");

            if (It.IsInRange(thisBatchScript.Type, TypeOfBatchScript.Statement))
            {
                var content = Pseudonyms.ReplaceTokensIn(thisBatchScript.Command, withSupplementaryTokenReplacements);
                UsingConnection(inThisContext, x => RunCommand(content, x));
                return;
            }

            var batches = GetSQLOperations(thisBatchScript.Command, withSupplementaryTokenReplacements);

            Emitter.Publish(Indentation.FirstLevel, $"Batch contains {batches.Count} statement{(batches.Count > 1 ? "s" : string.Empty)}.");

            Run(batches.AsSafeReadOnlyList(), inThisContext);
        }
 /// <summary>
 /// Creates a connection context.
 /// </summary>
 /// <param name="usingConnection">using connection.</param>
 /// <returns>
 /// a connection context
 /// </returns>
 public IConnectionContext Create(IConnectionDetail usingConnection)
 {
     return(new ConnectionContext
     {
         Connection = new SqlConnection(usingConnection.SQLDetail),
         Detail = usingConnection
     });
 }
        /// <summary>
        /// Drop the data store.
        /// </summary>
        /// <param name="usingStoreName">using the name of the store.</param>
        /// <param name="inThisContext">in this context.</param>
        public void DropDataStore(string usingStoreName, IConnectionDetail inThisContext)
        {
            It.IsEmpty(usingStoreName)
            .AsGuard <ArgumentNullException>(nameof(usingStoreName));
            It.IsNull(inThisContext)
            .AsGuard <ArgumentNullException>(nameof(inThisContext));

            var command = $"drop database [{usingStoreName}]";

            UsingConnection(inThisContext, x => RunCommand(command, x));
        }
        /// <summary>
        /// Data store exists?
        /// </summary>
        /// <param name="usingStoreName">using the name of the store.</param>
        /// <param name="inThisContext">in this context.</param>
        /// <returns>
        /// the running task containing the result
        /// </returns>
        public bool DataStoreExists(string usingStoreName, IConnectionDetail inThisContext)
        {
            It.IsEmpty(usingStoreName)
            .AsGuard <ArgumentNullException>(nameof(usingStoreName));
            It.IsNull(inThisContext)
            .AsGuard <ArgumentNullException>(nameof(inThisContext));

            var usingCommand = $"if exists (select * from sys.databases where name = '{usingStoreName}') select 1 else select 0";

            return(GetAtom <bool>(usingCommand, inThisContext));
        }
        /// <summary>
        /// Sets the learner counts.
        /// </summary>
        /// <param name="forConnection">for connection</param>
        /// <param name="usingProvider">using provider</param>
        public void SetLearnerCounts(IConnectionDetail forConnection, ILearningProvider usingProvider)
        {
            var valids = GetSchemaLearnerCount(forConnection, "valid");

            //var invalids = GetSchemaLearnerCount(forConnection, "invalid");

            Emitter.Publish(Indentation.FirstLevel, $"{valids} valid record(s) created");
            //Emitter.Publish(Indentation.FirstLevel, $"{invalids} invalid record(s) created");

            Monitor.SetLearnerCounts(valids, usingProvider.LearnerCount, valids);
        }
        /// <summary>
        /// Loads...
        /// </summary>
        /// <param name="intoSource">into source.</param>
        /// <param name="onMaster">on master.</param>
        /// <param name="fromInputFile">from input file.</param>
        /// <returns>
        /// the currently running task
        /// </returns>
        public async Task Load(IConnectionDetail intoSource, IConnectionDetail onMaster, string fromInputFile)
        {
            await Task.Run(async () =>
            {
                It.IsNull(intoSource)
                    .AsGuard<ArgumentNullException>(nameof(intoSource));
                It.IsNull(onMaster)
                    .AsGuard<ArgumentNullException>(nameof(onMaster));
                It.IsEmpty(fromInputFile)
                    .AsGuard<ArgumentNullException>(nameof(fromInputFile));

                //if (Context.DataStoreExists(intoSource.Name, onMaster))
                //{
                //    Context.DropDataStore(intoSource.Name, onMaster);
                //}

                Emitter.Publish($"Creating data store: {intoSource.DBName}");

                //Context.CreateDataStore(intoSource.Name, onMaster);

                var content = await FileManager.Load(fromInputFile); // <= very lazy and inefficient..
                var messageNamespace = GetHeaderNameSpace(content);

                It.IsEmpty(messageNamespace)
                    .AsGuard<ArgumentException, Localised>(Localised.UnableToRetrieveMessageNamespace);

                var buildSchema = await Schema.Generate(
                    messageNamespace,
                    intoSource,
                    (inContext, loadSchemaPath, createTables) =>
                    {
                        var loader = GetLoader(inContext, createTables);
                        loader.Execute(loadSchemaPath, fromInputFile);
                    });

                Mediator.Publish(ChangeYearMessage.Create(buildSchema.Year, buildSchema.Collection));

                var batchList = Batches.GetBatch(BatchProcessName.BuildSourceDataStore, buildSchema.Year);
                var s = batchList.Scripts.ElementAt(1).Command;
                if (s.Contains("ILR"))
                {
                    s = Regex.Replace(s, @"[A-Z]\w+-[0-9]\w+-[0-9]\w+-[0-9]\w+-[0-9]\w+-[0-9]\w+", Path.GetFileNameWithoutExtension(fromInputFile));
                }
                else
                {
                    s = s.Replace("originalFileName", Path.GetFileNameWithoutExtension(fromInputFile));
                }
                batchList.Scripts.ElementAt(1).Command = s;

                Emitter.Publish(batchList.Description);

                Context.Run(batchList.Scripts, intoSource);
            });
        }
        /// <summary>
        /// Store table exists.
        /// </summary>
        /// <param name="usingThisName">using this name.</param>
        /// <param name="inThisContext">in this context.</param>
        /// <returns>
        /// true if it does
        /// </returns>
        public bool StoreTableExists(string usingThisName, IConnectionDetail inThisContext)
        {
            It.IsEmpty(usingThisName)
            .AsGuard <ArgumentNullException>(nameof(usingThisName));
            It.IsNull(inThisContext)
            .AsGuard <ArgumentNullException>(nameof(inThisContext));

            var usingCommand = $"if object_id('{usingThisName}','u') is not null select 1 else select 0";

            return(GetAtom <bool>(usingCommand, inThisContext));
        }
Beispiel #15
0
        /// <summary>
        /// Gets the provider details.
        /// </summary>
        /// <param name="usingDetail">using detail.</param>
        /// <param name="providerIDs">provider ids.</param>
        /// <returns>
        /// returns a list of enriched provider details
        /// </returns>
        public IReadOnlyCollection <IProviderDetails> GetProviderDetails(IConnectionDetail usingDetail, IReadOnlyCollection <int> providerIDs)
        {
            if (It.IsEmpty(providerIDs))
            {
                return(Collection.EmptyAndReadOnly <IProviderDetails>());
            }

            var script = GetScript(BatchProcessName.GetProviderDetails);

            script = Substitute.ReplaceTokensIn(script, x => x.Replace("${providerIDs}", string.Join(",", providerIDs)));

            return(Context.GetItems <ProviderDetails, IProviderDetails>(script, usingDetail, "Name"));
        }
        /// <summary>
        /// Gets the loader.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="makeNew">if set to <c>true</c> [make new].</param>
        /// <returns>
        /// a bulk loader
        /// </returns>
        public ISQLXMLBulkLoad4 GetLoader(IConnectionDetail context, bool makeNew)
        {
            It.IsNull(context)
                .AsGuard<ArgumentNullException>(nameof(context));

            return new SQLXMLBulkLoad4
            {
                ConnectionString = context.COMDetail,
                ErrorLogFile = "LoadErrors.xml",
                KeepIdentity = false,
                SGDropTables = makeNew,
                SchemaGen = makeNew,
            };
        }
        /// <summary>
        /// Runs..
        /// </summary>
        /// <param name="theseBatchItems">these batch items.</param>
        /// <param name="inThisContext">in this context.</param>
        /// <param name="withSupplementaryTokenReplacements">with supplementary token replacements.</param>
        public void Run(
            IReadOnlyCollection <ISQLBatchScript> theseBatchItems,
            IConnectionDetail inThisContext,
            Func <string, string> withSupplementaryTokenReplacements)
        {
            // note: empty is safe, null is not...
            It.IsNull(theseBatchItems)
            .AsGuard <ArgumentNullException>(nameof(theseBatchItems));
            It.IsNull(inThisContext)
            .AsGuard <ArgumentNullException>(nameof(inThisContext));

            theseBatchItems
            .ForEach(script => Run(script, inThisContext, withSupplementaryTokenReplacements));
        }
        /// <summary>
        /// Get atom...
        /// </summary>
        /// <typeparam name="TReturn">The type of the return.</typeparam>
        /// <param name="usingThisCommand">using this command.</param>
        /// <param name="inThisContext">in this context.</param>
        /// <returns>
        /// an atom of type <typeparamref name="TReturn" />
        /// </returns>
        public TReturn GetAtom <TReturn>(string usingThisCommand, IConnectionDetail inThisContext)
        {
            It.IsEmpty(usingThisCommand)
            .AsGuard <ArgumentNullException>(nameof(usingThisCommand));
            It.IsNull(inThisContext)
            .AsGuard <ArgumentNullException>(nameof(inThisContext));

            return(UsingConnection(inThisContext, x =>
            {
                using (var cmd = CreateCommand(usingThisCommand, x))
                {
                    var result = cmd.ExecuteScalar();
                    return GetValue <TReturn>(result);
                }
            }));
        }
Beispiel #19
0
        /// <summary>
        /// Runs...
        /// </summary>
        /// <param name="script">The script.</param>
        /// <param name="inContext">in context.</param>
        /// <param name="forCandidate">for candidate.</param>
        public void RunScript(ISQLBatchScript script, IConnectionDetail inContext, int forProvider, ref string forCandidate)
        {
            var result = Task.Run(async() =>
            {
                It.IsOutOfRange(script.Type, TypeOfBatchScript.File)
                .AsGuard <ArgumentException>($"{script.Type}");

                Emitter.Publish(Localised.PerformingExportScript, script.Description);

                var commandPath = Path.Combine(Location.OfAssets, script.Command);
                var command     = await FileManager.Load(commandPath);
                command         = Token.DoSecondaryPass(command, forProvider);

                return(Context.GetAtom <string>(command, inContext));
            }).Result;

            forCandidate = forCandidate.Replace(script.Description, result);

            Emitter.Publish(Indentation.FirstLevel, CommonLocalised.Completed);
        }
        /// <summary>
        /// Generates the schema.
        /// </summary>
        /// <param name="forMessageNamespace">for message namespace.</param>
        /// <param name="inContext">in context.</param>
        /// <param name="andExecuteBulkload">and execute (a) bulk load</param>
        /// <returns>
        /// the schema map sued to generate the data source
        /// </returns>
        public async Task <ISchemaMap> Generate(string forMessageNamespace, IConnectionDetail inContext, Action <IConnectionDetail, string, bool> andExecuteBulkload)
        {
            It.IsEmpty(forMessageNamespace)
            .AsGuard <ArgumentNullException>(nameof(forMessageNamespace));
            It.IsNull(andExecuteBulkload)
            .AsGuard <ArgumentNullException>(nameof(andExecuteBulkload));

            return(await Task.Run(() =>
            {
                var schemaMap = Schemas.GetSchema(forMessageNamespace);

                It.IsNull(schemaMap)
                .AsGuard <ArgumentException, Localised>(Localised.FailedToObtainSchemaMap);

                var loadSchemaPath = Path.Combine(Location.OfAssets, schemaMap.BulkLoad);
                var messageSchemaPath = Path.Combine(Location.OfAssets, schemaMap.Message);
                var relationshipsPath = Path.Combine(Location.OfAssets, "relationships.xml");

                SQLDatabase.Open(inContext.SQLDetail);

                var sqlSchema = new SQLSchema(messageSchemaPath);
                var relations = GetRelations(relationshipsPath, sqlSchema.NameSpace);
                sqlSchema.SetRelationships(relations);

                var autoGenerateTables = false;
                //var newPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "newSchema.xml");
                //var buildSchema = sqlSchema.GenerateBulkLoadSchemaWithIdentity();
                //buildSchema.Save(newPath);

                if (!autoGenerateTables)
                {
                    sqlSchema.CreateTables();
                }

                andExecuteBulkload(inContext, loadSchemaPath, autoGenerateTables);

                SQLDatabase.Close();

                return schemaMap;
            }));
        }
        /// <summary>
        /// Using a connection.
        /// </summary>
        /// <param name="inThisContext">in this context; here meaning the connection details</param>
        /// <param name="runThisAction">run this action.</param>
        public void UsingConnection(IConnectionDetail inThisContext, Action <IConnectionContext> runThisAction)
        {
            It.IsNull(inThisContext)
            .AsGuard <ArgumentNullException>(nameof(inThisContext));
            It.IsNull(runThisAction)
            .AsGuard <ArgumentNullException>(nameof(runThisAction));

            using (var con = Factory.Create(inThisContext))
            {
                try
                {
                    con.OpenSafe();
                    runThisAction(con);
                }
                catch (Exception e)
                {
                    Emitter.Publish(e.Message);
                    throw;
                }
            }
        }
        /// <summary>
        /// Using a connection.
        /// </summary>
        /// <typeparam name="TReturn">The type of the return.</typeparam>
        /// <param name="inThisContext">in this context; here meaning the connection details</param>
        /// <param name="runThisAction">run this action.</param>
        /// <returns>
        /// the result of the function call
        /// </returns>
        public TReturn UsingConnection <TReturn>(IConnectionDetail inThisContext, Func <IConnectionContext, TReturn> runThisAction)
        {
            It.IsNull(inThisContext)
            .AsGuard <ArgumentNullException>(nameof(inThisContext));
            It.IsNull(runThisAction)
            .AsGuard <ArgumentNullException>(nameof(runThisAction));

            using (var con = Factory.Create(inThisContext))
            {
                try
                {
                    Emitter.Publish($"UsingConnection");
                    con.OpenSafe();
                    return(runThisAction(con));
                }
                catch (Exception)
                {
                    throw;
                }
            }
        }
Beispiel #23
0
        /// <summary>
        /// Builds the rules engine.
        /// </summary>
        /// <param name="session">The session.</param>
        /// <param name="context">The context.</param>
        /// <returns>the OPA rule engine wrapper</returns>
        public OPAWrapperLib BuildRulesEngine(IConnectionDetail context, IRulebaseConfiguration rulebase, bool depositXDSFiles)
        {
            var opaConfiguration = Configuration.GetOPAConfigurationFor(rulebase);

            var wrapper = new OPAWrapperLib(opaConfiguration.AsDocument());

            wrapper.XslFile = Configuration.GetOPATransformationPathFor(rulebase);
            wrapper.SetLoggingLevel(LoggingType.Error);
            wrapper.EnableTiming = false;
            wrapper.Log2Console  = false;

            if (depositXDSFiles)
            {
                var dumpPath = Manager.CreateOperatingFolder("Easy OPA Rulebase Files", rulebase.ShortName, rulebase.OperatingYear.AsString()).Result;
                wrapper.DumpXdsFileName = "UKPRN@global,LearnRefNumber@Learner";
                wrapper.DumpXdsPath     = dumpPath;
            }

            wrapper.AddConString("LoggingDB", context.SQLDetail);
            wrapper.AddConString("ILR", context.SQLDetail); // ???
            wrapper.NumberOfThreads = rulebase.DegreeOfParallelism;

            return(wrapper);
        }
        public string GetILRFileName(IConnectionDetail forConnection)
        {
            var command = "select TOP(1) concat('ILR-', UKPRN,'-', FORMAT([DateTime], 'ddMMyyyy'),'-',FORMAT([DateTime],'hhmmss'), '-' , SerialNo) from dbo.Source;";

            return(RunSafe.Try(() => Coordinate.GetAtom <string>(command, forConnection)));
        }
 public void ExecuteCommand(string command, IConnectionDetail context)
 {
     UsingConnection(context, x => RunCommand(command, x));
 }
Beispiel #26
0
        /// <summary>
        /// Creates the schema for...
        /// </summary>
        /// <param name="inContext">in context.</param>
        /// <param name="usingSchemaScripts">using schema scripts.</param>
        /// <param name="withSecondaryReplacements">with secondary replacements.</param>
        /// <returns></returns>
        public void CreateSchemaFor(IConnectionDetail inContext, IReadOnlyCollection <ISQLBatchScript> usingSchemaScripts, Func <string, string> withSecondaryReplacements)
        {
            Emitter.Publish(Indentation.FirstLevel, $"Adding structures to {inContext.DBName} data store");

            Context.Run(usingSchemaScripts, inContext, withSecondaryReplacements);
        }
        /// <summary>
        /// Gets the schema learner count.
        /// </summary>
        /// <param name="forConnection">For connection</param>
        /// <param name="thisSchema">(and) this schema</param>
        /// <returns>the count</returns>
        public int GetSchemaLearnerCount(IConnectionDetail forConnection, string thisSchema)
        {
            var command = $"select count(*) from {thisSchema}.Learner";

            return(RunSafe.Try(() => Coordinate.GetAtom <int>(command, forConnection)));
        }
        /// <summary>
        /// Gets the items.
        /// this is a very simple list hydration class
        /// </summary>
        /// <typeparam name="TReturn">The return type.</typeparam>
        /// <typeparam name="TContract">the returning contract type</typeparam>
        /// <param name="usingThisCommand">using this command.</param>
        /// <param name="inThisContext">in this context.</param>
        /// <param name="mappedProperties">with mapped properties.</param>
        /// <returns>
        /// an list of type <typeparamref name="TContract" />
        /// </returns>
        public IReadOnlyCollection <TContract> GetItems <TReturn, TContract>(string usingThisCommand, IConnectionDetail inThisContext, params string[] mappedProperties)
            where TContract : class
            where TReturn : class, TContract, new()
        {
            It.IsEmpty(usingThisCommand)
            .AsGuard <ArgumentNullException>(nameof(usingThisCommand));
            It.IsNull(inThisContext)
            .AsGuard <ArgumentNullException>(nameof(inThisContext));

            return(UsingConnection(inThisContext, x =>
            {
                using (var cmd = CreateCommand(usingThisCommand, x))
                {
                    using (var reader = cmd.ExecuteReader())
                    {
                        return CollectionFromDataReader <TReturn, TContract>(reader, mappedProperties);
                    }
                }
            }));
        }
        /// <summary>
        /// Clone...
        /// </summary>
        /// <param name="usingMappings">using (table) mappings.</param>
        /// <param name="fromDataSource">from data source.</param>
        /// <param name="toDataTarget">to data target.</param>
        /// <param name="forProvider">for provider.</param>
        public void Clone(IReadOnlyCollection <IMapCloneEntityDetails> usingMappings, IConnectionDetail fromDataSource, IConnectionDetail toDataTarget, int forProvider)
        {
            using (var writeConnection = new SqlConnection(toDataTarget.SQLDetail))
            {
                Emitter.Publish($"{this.ToString()}.Clone");
                writeConnection.Open();
                var sqlTransaction = writeConnection.BeginTransaction();

                try
                {
                    using (var readConnection = new SqlConnection(fromDataSource.SQLDetail))
                    {
                        readConnection.Open();

                        using (var copier = Build(writeConnection, sqlTransaction))
                        {
                            usingMappings.ForEach(mapping =>
                            {
                                Configure(copier, mapping);

                                Emitter.Publish(Indentation.FirstLevel, Localised.CloningDataFormat, mapping.Master);

                                var command = $"select {string.Join(", ", mapping.Attributes.Select(x => x.Master))} from {mapping.Master} where UKPRN = {forProvider}";
                                Execute(command, readConnection, x => copier.WriteToServer(x));
                            });
                        }
                    }

                    sqlTransaction.Commit();
                    Emitter.Publish(Indentation.FirstLevel, CommonLocalised.Completed);
                }

                catch (Exception exception)
                {
                    Emitter.Publish(exception.Message);
                    sqlTransaction.Rollback();

                    throw (exception);
                }
            }
        }
 /// <summary>
 /// Runs..
 /// </summary>
 /// <param name="theseBatchItems">these batch items.</param>
 /// <param name="inThisContext">in this context.</param>
 public void Run(IReadOnlyCollection <string> theseBatchItems, IConnectionDetail inThisContext)
 {
     UsingConnection(inThisContext, x => theseBatchItems.ForEach(item => RunCommand(item, x)));
 }