diff --git a/NAV Source Control Test Host/Program.cs b/NAV Source Control Test Host/Program.cs index 8fc71a6..619fba7 100644 --- a/NAV Source Control Test Host/Program.cs +++ b/NAV Source Control Test Host/Program.cs @@ -67,13 +67,29 @@ namespace NavScm.TestHost log.DebugFormat("Type {0}, ID {1}, Name {2}, Modified {3} {4}, Version {5}", o2.Type, o2.ID, o2.Name, o2.Date.ToShortDateString(), o2.Time.ToShortTimeString(), o2.Version_List); + log.Debug("=== Exporting sample objects ==="); + DevEnvInterface devenv = new DevEnvInterface("C:\\Program Files (x86)\\Microsoft Dynamics NAV\\tbrt-nav-erp-02\\RoleTailored Client\\finsql.exe", "tbrt-sql-erp-01", "TERRABIT 2015 DEV"); devenv.Export(loadedObjects["5.80"], $"{Directory.GetCurrentDirectory()}\\CU80.txt"); + devenv.Export(loadedObjects["5.99996"], $"{Directory.GetCurrentDirectory()}\\CU99996.txt"); devenv.Export(loadedObjects["5.99997"], $"{Directory.GetCurrentDirectory()}\\CU99997.txt"); + devenv.Export(loadedObjects["5.99998"], $"{Directory.GetCurrentDirectory()}\\CU99998.txt"); devenv.Export(loadedObjects["1.13"], $"{Directory.GetCurrentDirectory()}\\TAB13.txt"); + //log.Debug("=== Importing TN_WORK ==="); + + //o2 = devenv.Import(loadedObjects["5.99997"], $"{Directory.GetCurrentDirectory()}\\CU99997.txt"); + //log.DebugFormat("Object after import: Type {0}, ID {1}, Name {2}, Modified {3} {4}, Version {5}", + // o2.Type, o2.ID, o2.Name, o2.Date.ToShortDateString(), o2.Time.ToShortTimeString(), o2.Version_List); + + //log.Debug("=== Compiling TN_WORK ==="); + + //o2 = devenv.Compile(loadedObjects["5.99997"]); + //log.DebugFormat("Object after compilation: Type {0}, ID {1}, Name {2}, Modified {3} {4}, Version {5}", + // o2.Type, o2.ID, o2.Name, o2.Date.ToShortDateString(), o2.Time.ToShortTimeString(), o2.Version_List); + log.Info("Shutting down..."); Console.ReadLine(); diff --git a/NAVSCM Library/NavInterface/DevEnvInterface.cs b/NAVSCM Library/NavInterface/DevEnvInterface.cs index 64555a5..c9c5eec 100644 --- a/NAVSCM Library/NavInterface/DevEnvInterface.cs +++ b/NAVSCM Library/NavInterface/DevEnvInterface.cs @@ -23,6 +23,11 @@ namespace NavScm.NavInterface { private static readonly log4net.ILog log = log4net.LogManager.GetLogger(typeof(DevEnvInterface)); + /// + /// The Context to use for DB operations. + /// + private NavSQLDataContext navSqlContext; + /// /// Helper structure to capture the full execution result of finsql.exe. /// @@ -102,6 +107,8 @@ namespace NavScm.NavInterface DatabaseServer = databaseServer; DatabaseName = databaseName; + navSqlContext = new NavSQLDataContext($"Data Source=\"{DatabaseServer}\";Initial Catalog=\"{DatabaseName}\";Integrated Security=True"); + if (log.IsDebugEnabled) { log.Debug($"Constructed and attached to DevEnv {DevEnvPath}"); @@ -260,7 +267,7 @@ namespace NavScm.NavInterface // TODO: Skip Unlicensed objects? string command = $"Command=ExportObjects,File=\"{destinationFileName}\",Filter=\"{obj.GetFilter()}\""; - log.DebugFormat("Export: Build command string: {0}", command); + log.DebugFormat("Export: Built command string: {0}", command); var result = ExecuteCommand(command); if (! result.Success) { @@ -268,5 +275,61 @@ namespace NavScm.NavInterface } } + /// + /// Imports a given NAV object into the database from the file given. The existing file is overwritten, + /// schema changes are executed forcibly, so beware of possible data loss. + /// + /// + /// The file name must end with .txt, as finsql.exe deduces the export format from the destiation files + /// extension (crap). We have no other option here as to play by these rules. + /// Be aware, that NAV uses some strange mix of CP850 and CP1252 to encode the text files, + /// this is mean stuff here. The call does not try to convert this into something more sensible + /// at this point, especially since the IDE won't be able to handle this properly if you have to + /// work with the files manually. Checked with NAV 2015, YMMV. + /// Check http://forum.mibuso.com/discussion/37078/encoding-of-exported-navision-objects-txt-files + /// for further details about this. + /// The NAV object as taken from the SQL database or from the cache (doesn't matter). + /// The name of the source file. The file name must end with .txt. + /// A new NavObject representing the imported object. + public NavObject Import(NavObject obj, string sourceFileName) + { + Contract.Requires(obj != null); + Contract.Requires(sourceFileName != ""); + Contract.Requires(Path.GetExtension(sourceFileName) == ".txt"); + + // TODO: Skip Unlicensed objects? + string command = $"Command=ImportObjects,File=\"{sourceFileName}\",ImportAction=overwrite,SynchronizeSchemaChanges=force"; + log.DebugFormat("Import: Built command string: {0}", command); + var result = ExecuteCommand(command); + if (!result.Success) + { + throw new ArgumentException($"Cannot import object {obj.NavType} ID {obj.ID} from file {sourceFileName}: {result.ErrorMessage}"); + } + + return navSqlContext.NavObject.Where(o => o.Type == obj.Type && o.ID == obj.ID).First(); + } + + + /// + /// Compiles the NavObject given and reloads its object descriptor from the database. Compilation is done with + /// forced schema changes, so beware of possible data loss. + /// + /// The NAV object as taken from the SQL database or from the cache (doesn't matter). + /// A new NavObject representing the imported object. + public NavObject Compile(NavObject obj) + { + Contract.Requires(obj != null); + + // TODO: Skip Unlicensed objects? + string command = $"Command=CompileObjects,Filter=\"{obj.GetFilter()}\",SynchronizeSchemaChanges=force"; + log.DebugFormat("Compile: Built command string: {0}", command); + var result = ExecuteCommand(command); + if (!result.Success) + { + throw new ArgumentException($"Cannot compile object {obj.NavType} ID {obj.ID}: {result.ErrorMessage}"); + } + + return navSqlContext.NavObject.Where(o => o.Type == obj.Type && o.ID == obj.ID).First(); + } } }