using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Tango.BL; using Tango.BL.Entities; using Tango.Core; using Tango.Core.Helpers; namespace Tango.CctOptimizer.CLI { class Program { static void Main(string[] args) { DataSource dataSource = new DataSource(); dataSource.Catalog = "Tango_DEV"; dataSource.Address = "twine.database.windows.net"; dataSource.IntegratedSecurity = false; dataSource.UserName = "Roy"; dataSource.Password = "Aa123456"; RESTART: Console.Write("Checking CCT Optimizations..."); long totalBytes = 0; List toRemove = new List(); List allCCT = new List(); List allRmls = new List(); try { using (ObservablesContext db = ObservablesContext.CreateDefault(dataSource)) { allRmls = db.Rmls.Where(x => x.CctGuid != null).ToList(); var cctsGuids = db.Ccts.Select(x => x.Guid).ToList(); int cctCount = cctsGuids.Count; int cctCounter = 0; foreach (var guid in cctsGuids) { var cct = db.Ccts.SingleOrDefault(x => x.Guid == guid); allCCT.Add(cct); cctCounter++; ClearCurrentConsoleLine(); Console.Write($"Checking CCT Optimizations... {(int)((double)cctCounter / (double)cctCount * 100d)}%"); } Console.WriteLine(); Console.WriteLine(); //NOT USED var notUsedCCT = allCCT.Where(x => !allRmls.Exists(y => y.CctGuid == x.Guid)).ToList(); Console.WriteLine($"Not used CCT ({notUsedCCT.Count}):"); Console.WriteLine("---------------------------------------"); foreach (var cct in notUsedCCT) { long length = cct.Data != null ? cct.Data.Length : 0; totalBytes += length; toRemove.Add(cct); Console.WriteLine($"{(cct.FileName != null ? cct.FileName : "N/A")} - {FileHelper.GetFriendlyFileSize(length)}"); } //DUPLICATES List toExamine = allCCT.Where(x => x.FileName != null).Where(x => !notUsedCCT.Contains(x)).ToList(); List uniqueCCTs = toExamine.DistinctBy(x => x.FileName).ToList(); List duplicates = new List(); foreach (var cct in toExamine) { if (uniqueCCTs.Exists(x => x != cct && x.FileName == cct.FileName)) { duplicates.Add(cct); } } Console.WriteLine(); Console.WriteLine(); Console.WriteLine($"Duplicates CCT ({duplicates.Count}):"); Console.WriteLine("---------------------------------------"); foreach (var duplicateGroup in duplicates.GroupBy(x => x.FileName)) { long length = duplicateGroup.First().Data != null ? duplicateGroup.First().Data.Length * duplicateGroup.Count() : 0; totalBytes += length; foreach (var cct in duplicateGroup) { toRemove.Add(cct); } Console.WriteLine($"{(duplicateGroup.First().FileName != null ? duplicateGroup.First().FileName : "N/A")} - {FileHelper.GetFriendlyFileSize(length)} {(duplicateGroup.Count() > 1 ? $"X{duplicateGroup.Count()}" : String.Empty)}"); } Console.WriteLine(); Console.WriteLine(); Console.WriteLine($"Total CCT's found: {allCCT.Count}"); Console.WriteLine($"Optimization will delete {toRemove.Count} CCT records ({FileHelper.GetFriendlyFileSize(totalBytes)})"); Console.WriteLine(); if (toRemove.Count > 0) { Console.Write("Press 'Y' to start optimization procedure."); var key = Console.ReadKey(); if (key.Key != ConsoleKey.Y) { Environment.Exit(0); return; } } else { Console.WriteLine("Press enter to exit to optimizer..."); Console.ReadLine(); Environment.Exit(0); return; } //Reassign RMLs from duplicates... Console.WriteLine(); Console.WriteLine(); Console.WriteLine("Reassigning RMLs CCTS..."); Console.WriteLine("---------------------------------------"); Console.WriteLine(); foreach (var rml in allRmls) { var duplicateCCT = duplicates.SingleOrDefault(x => x.Guid == rml.CctGuid); if (duplicateCCT != null) { var uniqueCCT = uniqueCCTs.SingleOrDefault(x => x.FileName == duplicateCCT.FileName); Console.WriteLine($"Reassigning RML '{rml.Name}' to '{uniqueCCT.FileName} (ID: {uniqueCCT.ID})'..."); rml.CctGuid = uniqueCCT.Guid; db.SaveChanges(); } } //Remove unused and duplicate CCTs... Console.WriteLine(); Console.WriteLine(); Console.WriteLine("Removing CCT's..."); Console.WriteLine("---------------------------------------"); Console.WriteLine(); foreach (var cct in toRemove) { Console.WriteLine($"Removing '{cct.FileName}' ID: {cct.ID}..."); cct.DeleteCascadeAsync(db).Wait(); } Console.WriteLine(); Console.WriteLine(); Console.WriteLine("Optimization Completed."); Console.WriteLine(); Console.WriteLine(); goto RESTART; } } catch (Exception ex) { Console.WriteLine(); Console.WriteLine(); Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("Error occurred while trying to perform the optimization."); Console.WriteLine(ex.ToString()); Console.WriteLine(); Console.WriteLine(); Console.ReadLine(); } } public static void ClearCurrentConsoleLine() { int currentLineCursor = Console.CursorTop; Console.SetCursorPosition(0, Console.CursorTop); Console.Write(new string(' ', Console.WindowWidth)); Console.SetCursorPosition(0, currentLineCursor); } } }