/// <summary>
        /// Warning!  Will *really* flush the directory or throw exception.
        /// Can't just call the overload to Directory.Delete that is recursive because we need to call ClearAttributes on every file.
        /// </summary>
        /// <param name="dir">Directory to flush.</param>
        /// <param name="logger">Startup logger because we have no DI.</param>
        /// <param name="deleteDirAfterFlush">Whether to delete the actual directory after flushing it.</param>
        /// <returns>If failure, it probably can't flush an existing directory due to a locked file.</returns>
        public static bool FlushDirectory(string dir, IStartupLogger logger, bool deleteDirAfterFlush = false)
        {
            if (Directory.Exists(dir))
            {
                FlushFilesFromDirectory(dir, logger);

                if (Directory.EnumerateFiles(dir, SEARCH_ALL_FILES).Any())
                {
                    return(false);  // a file was locked
                }
                else
                {
                    foreach (var d in Directory.EnumerateDirectories(dir))
                    {
                        if (!FlushDirectory(d, logger, deleteDirAfterFlush))
                        {
                            return(false);
                        }
                    }
                    if (deleteDirAfterFlush)
                    {
                        DeleteDirectory(dir);
                    }
                    return(true);
                }
            }
            else
            {
                return(true);
            }
        }
 private static void FlushFilesFromDirectory(string currentDir, IStartupLogger logger)
 {
     if (Directory.Exists(currentDir))
     {
         foreach (var file in Directory.EnumerateFiles(currentDir))
         {
             FileUtils.SafeDeleteFile(file, true, logger);
         }
     }
 }
 internal JournalTable(string connectionString,
                       IStartupLogger log,
                       string journalTableCreationScript,
                       Server serverConnection,
                       Dictionary <int, string> failedScripts)
     : base(log)
 {
     _connectionString           = connectionString;
     _journalTableCreationScript = journalTableCreationScript;
     _failedScripts    = failedScripts; // share failed scripts with DatabaseMigrator
     _serverConnection = serverConnection;
 }
        /// <summary>
        /// At time of writing, Smo has a bug with the utility command 'go'.  It blows up on some proper queries containing go.
        /// Not sure what the heck, but in DatabaseMigrator.cs we call server.ConnectionContext.ExecuteNonQuery and go works.  Here we call ExecuteReader and it doesn't.
        /// And this thread indicates it should never work.
        /// In any case, here we are splitting the scripts apart on go.
        /// https://github.com/microsoft/sqlmanagementobjects/issues/53
        /// </summary>
        internal static bool SchemaChanged(Server server, string sql, IStartupLogger log)
        {
            SplitOnGo splitter = new();

            foreach (var script in splitter.Split(sql))
            {
                if (SchemaChanged_Inner(server, script, log))
                {
                    return(true);
                }
            }
            return(false);
        }
예제 #5
0
        /// <summary>Safely deletes a file - no exception if operation fails</summary>
        /// <param name="path">File to delete</param>
        /// <param name="forceDelete">Try to alter flags (if necessary) to accomplish delete</param>
        /// <param name="logger">Startup logger because we have no DI.</param>
        public static void SafeDeleteFile(string path, bool forceDelete, IStartupLogger logger)
        {
            if (string.IsNullOrEmpty(path))
            {
                return;
            }

            try
            {
                if (File.Exists(path))
                {
                    if (forceDelete)
                    {
                        // Not wrapping SetAttributes() with try/catch since Delete() will fail if SetAttributes() fails.
                        if (File.GetAttributes(path) == FileAttributes.ReadOnly)
                        {
                            File.SetAttributes(path, FileAttributes.Normal);
                        }
                    }
                    File.Delete(path);
                }
            }
            catch (UnauthorizedAccessException e)
            {
                logger?.LogException(e);
            }
            catch (ArgumentException e)
            {
                logger?.LogException(e);
            }
            catch (PathTooLongException e)
            {
                logger?.LogException(e);
            }
            catch (DirectoryNotFoundException e)
            {
                logger?.LogException(e);
            }
            catch (IOException e)
            {
                logger?.LogException(e);
            }
            catch (NotSupportedException e)
            {
                logger?.LogException(e);
            }
        }
예제 #6
0
        /// <summary>
        /// xx
        /// </summary>
        /// <param name="s">Stream.</param>
        /// <param name="path">Path of file to create.</param>
        /// <returns>pass/fail</returns>
        /// <param name="logger">Startup logger because we have no DI.</param>
        public static bool StreamToFile(Stream s, string path, IStartupLogger logger)
        {
            if (s == null)
            {
                return(false);
            }

            try
            {
                using (var f = File.Create(path))
                {
                    s.Seek(0, SeekOrigin.Begin);
                    s.CopyTo(f);
                }
                return(true);
            }
            catch (UnauthorizedAccessException e)
            {
                logger?.LogException(e);
            }
            catch (ArgumentException e)
            {
                logger?.LogException(e);
            }
            catch (PathTooLongException e)
            {
                logger?.LogException(e);
            }
            catch (DirectoryNotFoundException e)
            {
                logger?.LogException(e);
            }
            catch (IOException e)
            {
                logger?.LogException(e);
            }
            catch (NotSupportedException e)
            {
                logger?.LogException(e);
            }

            return(false);
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="server"></param>
        /// <param name="script">A script that doesn't contain the go keyword.</param>
        /// <param name="log"></param>
        /// <returns></returns>
        private static bool SchemaChanged_Inner(Server server, string script, IStartupLogger log)
        {
            var result = false;

            server.ConnectionContext.ExecuteNonQuery(SQL_SERVER_SHOWPLAN);

            try
            {
                using SqlDataReader readerResult = server.ConnectionContext.ExecuteReader(script);
                var schema             = readerResult.GetSchemaTable();
                var statementTypeIndex = GetStatementTypeColIndex(schema);
                while (readerResult.Read())
                {
                    if (_ddlStatements.Any(s => readerResult[statementTypeIndex].ToString().ToLower().Contains(s)))
                    {
                        result = true;
                        break;
                    }
                }
            }
            catch (Exception ex)
            {
                log.LogInfo($"Error attempting to detect schema changing script: {ex.Message}");
                var inner = ex.InnerException;
                while (inner != null)
                {
                    log.LogInfo($"Schema changing error cont: {inner.Message}");
                    inner = inner.InnerException;
                }
            }
            finally
            {
                server.ConnectionContext.ExecuteNonQuery(SQL_SERVER_SHOWPLAN_OFF);
            }
            return(result);
        }
예제 #8
0
 /// <summary>
 /// Sets the startup IStartupLogger
 /// </summary>
 /// <param name="logger"></param>
 /// <returns></returns>
 public DefaultsExpression UseLogger(IStartupLogger logger)
 {
     Logger = logger ?? throw new ArgumentNullException(nameof(logger));
     return(this);
 }
예제 #9
0
 public DirectDatabaseConnection(IStartupLogger log) => _log = log;