From f65bfbd6e84fdffc71353acfe7c9ccca5b117c45 Mon Sep 17 00:00:00 2001
From: xiazhengtongxue <133085197+xiazhengtongxue@users.noreply.github.com>
Date: 星期五, 23 一月 2026 17:28:41 +0800
Subject: [PATCH] 手动取消、异常上报和数据库维护脚本

---
 项目代码/WCSServices/WIDESEAWCS_SystemServices/Sys_LogService.cs |  717 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 713 insertions(+), 4 deletions(-)

diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WCSServices/WIDESEAWCS_SystemServices/Sys_LogService.cs" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WCSServices/WIDESEAWCS_SystemServices/Sys_LogService.cs"
index 5dc5329..c3e3d19 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/WCSServices/WIDESEAWCS_SystemServices/Sys_LogService.cs"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WCSServices/WIDESEAWCS_SystemServices/Sys_LogService.cs"
@@ -1,4 +1,130 @@
-锘縰sing NPOI.HSSF.Record;
+锘�//using Microsoft.Data.SqlClient;
+//using NPOI.HSSF.Record;
+//using SkiaSharp;
+//using System;
+//using System.Collections.Generic;
+//using System.Linq;
+//using System.Linq.Expressions;
+//using System.Text;
+//using System.Threading.Tasks;
+//using WIDESEAWCS_Core.BaseServices;
+//using WIDESEAWCS_ISystemRepository;
+//using WIDESEAWCS_ISystemServices;
+//using WIDESEAWCS_Model.Models;
+
+//namespace WIDESEAWCS_SystemServices
+//{
+//    public class Sys_LogService : ServiceBase<Sys_Log, ISys_LogRepository>, ISys_LogService
+//    {
+//        private static DateTime? _lastExecutionDate = null;
+//        private readonly object _lock = new object();
+//        private const string DbName = "WIDESEA_HF";
+//        private const long MaxMdfSizeBytes = 8L * 1024 * 1024 * 1024; // 8GB
+//        private const int TargetShrinkSizeMB = 4500; // 4.5GB
+
+//        public Sys_LogService(ISys_LogRepository BaseDal) : base(BaseDal)
+//        {
+
+//        }
+
+//        public void DeleteOldLogs()
+//        {
+//            // 浣跨敤閿佺‘淇濈嚎绋嬪畨鍏�
+//            lock (_lock)
+//            {
+//                var today = DateTime.Today;
+
+//                // 妫�鏌ヤ粖澶╂槸鍚﹀凡缁忔墽琛岃繃
+//                if (_lastExecutionDate.HasValue && _lastExecutionDate.Value.Date == today)
+//                {
+//                    return;
+//                }
+//                try
+//                {
+//                    // 璁$畻3涓湀鍓嶇殑鏃ユ湡
+//                    var threeMonthsAgo = DateTime.Now.AddMonths(-3);
+//                    // 璁$畻3澶╁墠鐨勬棩鏈�
+//                    var sevenDaysAgo = DateTime.Now.AddDays(-3);
+//                    // 鐗瑰畾URL
+//                    var specificUrl = "http://11.2.30.141:10870/interfaces/api/amr/robotQuery";
+
+//                    // 鏋勫缓鍒犻櫎鏉′欢锛�3涓湀鍓嶇殑鏃ュ織 鎴� (3澶╁墠涓擴RL涓虹壒瀹氬湴鍧�鐨勬棩蹇�)
+//                    var result = BaseDal.Db.Deleteable<Sys_Log>()
+//                        .Where(log => log.EndDate < threeMonthsAgo ||
+//                                     (log.EndDate < sevenDaysAgo && log.Url == specificUrl))
+//                        .ExecuteCommand();
+//                    // 鏇存柊鏈�鍚庢墽琛屾棩鏈熶负浠婂ぉ
+//                    _lastExecutionDate = today;
+//                }
+//                catch (Exception ex)
+//                {
+//                    Console.WriteLine($"鎵ц鏃ュ織娓呯悊鏃跺彂鐢熼敊璇細{ex.Message}");
+//                    // 鍙戠敓閿欒鏃朵笉鏇存柊鏈�鍚庢墽琛屾棩鏈燂紝浠ヤ究閲嶈瘯
+//                }
+//            }
+//        }
+//        // 15澶╂墽琛屼竴娆℃槦鏈熷ぉ2鐐�
+//        public void CheckAndManageFileSize()
+//        {
+//            try
+//            {
+
+//                //                --妫�鏌ユ暟鎹簱鏂囦欢绌洪棿浣跨敤鎯呭喌
+//                //SELECT
+//                //    name AS[鏂囦欢閫昏緫鍚峕,
+//                //    physical_name AS[鐗╃悊璺緞],
+//                //    size/ 128.0 AS[褰撳墠澶у皬MB],
+//                //    FILEPROPERTY(name, 'SpaceUsed') / 128.0 AS[宸茬敤绌洪棿MB],
+//                //    size / 128.0 - FILEPROPERTY(name, 'SpaceUsed') / 128.0 AS[鍙敤绌洪棿MB],
+//                //    growth / 128 AS[澧為暱閲廙B],
+//                //    CASE is_percent_growth
+//                //        WHEN 1 THEN CAST(growth AS VARCHAR) +'%'
+//                //        ELSE CAST(growth/ 128 AS VARCHAR) +'MB'
+//                //    END AS[澧為暱鏂瑰紡]
+//                //FROM sys.database_files;
+//                using (var connection = new SqlConnection("Data Source=.;Initial Catalog=WIDESEA_HF;User ID=sa;Password=123456;Integrated Security=False;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False"))
+//                {
+//                    connection.Open();
+
+//                    // 妫�鏌ユ暟鎹簱鏂囦欢澶у皬
+//                    var sizeCheckSql = @"SELECT name AS [鏂囦欢閫昏緫鍚峕, size/128.0 AS [褰撳墠澶у皬MB], FILEPROPERTY(name, 'SpaceUsed')/128.0 AS [宸茬敤绌洪棿MB] FROM sys.database_files WHERE name = @dbName";
+
+//                    using (var command = new SqlCommand(sizeCheckSql, connection))
+//                    {
+//                        command.Parameters.AddWithValue("@dbName", DbName);
+//                        using (var reader = command.ExecuteReader())
+//                        {
+//                            if (reader.Read())
+//                            {
+//                                double currentSizeMB = Convert.ToDouble(reader["褰撳墠澶у皬MB"]);
+//                                double usedSpaceMB = Convert.ToDouble(reader["宸茬敤绌洪棿MB"]);
+
+//                                if (currentSizeMB > MaxMdfSizeBytes / (1024 * 1024))
+//                                {
+//                                    // 鎵ц鏀剁缉鏁版嵁搴�
+
+//                                }else
+//                                {
+//                                    // 鏁寸悊纰庣墖>30%
+
+//                                }
+//                            }
+//                        }
+//                    }
+//                }
+//            }
+//            catch (Exception ex)
+//            {
+//                throw new Exception($"鏂囦欢鐩戞帶澶辫触: {ex.Message}");
+//            }
+//        }
+
+
+//    }
+//}
+using Microsoft.Data.SqlClient;
+using NPOI.HSSF.Record;
+using SkiaSharp;
 using System;
 using System.Collections.Generic;
 using System.Linq;
@@ -15,11 +141,45 @@
     public class Sys_LogService : ServiceBase<Sys_Log, ISys_LogRepository>, ISys_LogService
     {
         private static DateTime? _lastExecutionDate = null;
+        private static DateTime? _lastFileSizeCheckDate = null;
+        private static DateTime? _lastBackupDate = null;
         private readonly object _lock = new object();
+        private readonly object _fileSizeLock = new object();
+        private readonly object _backupLock = new object();
+
+        private const string DbName = "WIDESEA_HF";
+        private const string ConnectionString = "Data Source=11.2.30.112;Initial Catalog=WIDESEA_HF;User ID=kuka;Password=kuka;Integrated Security=False;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False";
+        private const long MaxMdfSizeBytes = 8L * 1024 * 1024 * 1024; // 8GB
+        private const int TargetShrinkSizeMB = 4500; // 4.5GB
+        private const double FragmentationThreshold = 30.0; // 30%纰庣墖鐜囬槇鍊�
+        private const int MaintenanceIntervalDays = 15; // 15澶╂墽琛屼竴娆�
+        private const int BackupRetentionDays = 30; // 澶囦唤淇濈暀30澶�
+        private const string BackupBasePath = @"D:\DatabaseBackups"; // 澶囦唤鏂囦欢瀛樺偍鐩綍
+        private const bool UseBackupCompression = true; // 鏄惁浣跨敤澶囦唤鍘嬬缉
+        private const bool VerifyBackup = true; // 鏄惁楠岃瘉澶囦唤
+        private const int MaxBackupRetryCount = 3; // 鏈�澶ч噸璇曟鏁�
+        private const int BackupTimeoutSeconds = 7200; // 澶囦唤瓒呮椂鏃堕棿锛堢锛�
 
         public Sys_LogService(ISys_LogRepository BaseDal) : base(BaseDal)
         {
+            // 纭繚澶囦唤鐩綍瀛樺湪
+            EnsureBackupDirectory();
+        }
 
+        private void EnsureBackupDirectory()
+        {
+            try
+            {
+                if (!Directory.Exists(BackupBasePath))
+                {
+                    Directory.CreateDirectory(BackupBasePath);
+                }
+            }
+            catch (Exception ex)
+            {
+                Console.WriteLine($"鍒涘缓澶囦唤鐩綍澶辫触: {ex.Message}");
+                throw;
+            }
         }
 
         public void DeleteOldLogs()
@@ -39,14 +199,15 @@
                     // 璁$畻3涓湀鍓嶇殑鏃ユ湡
                     var threeMonthsAgo = DateTime.Now.AddMonths(-3);
                     // 璁$畻3澶╁墠鐨勬棩鏈�
-                    var sevenDaysAgo = DateTime.Now.AddDays(-3);
+                    var threeDaysAgo = DateTime.Now.AddDays(-3);
                     // 鐗瑰畾URL
                     var specificUrl = "http://11.2.30.141:10870/interfaces/api/amr/robotQuery";
+                    var anonUrl = "http://11.2.30.111/anon/api/kuka/drivestatus";
 
-                    // 鏋勫缓鍒犻櫎鏉′欢锛�3涓湀鍓嶇殑鏃ュ織 鎴� (7澶╁墠涓擴RL涓虹壒瀹氬湴鍧�鐨勬棩蹇�)
+                    // 鏋勫缓鍒犻櫎鏉′欢锛�3涓湀鍓嶇殑鏃ュ織 鎴� (3澶╁墠涓擴RL涓虹壒瀹氬湴鍧�鐨勬棩蹇�)
                     var result = BaseDal.Db.Deleteable<Sys_Log>()
                         .Where(log => log.EndDate < threeMonthsAgo ||
-                                     (log.EndDate < sevenDaysAgo && log.Url == specificUrl))
+                                     (log.EndDate < threeDaysAgo && (log.Url == specificUrl || log.Url == anonUrl)))
                         .ExecuteCommand();
                     // 鏇存柊鏈�鍚庢墽琛屾棩鏈熶负浠婂ぉ
                     _lastExecutionDate = today;
@@ -54,9 +215,557 @@
                 catch (Exception ex)
                 {
                     Console.WriteLine($"鎵ц鏃ュ織娓呯悊鏃跺彂鐢熼敊璇細{ex.Message}");
+                    throw new Exception($"鏃ュ織娓呯悊鏃跺彂鐢熼敊璇�: {ex.Message}", ex);
                     // 鍙戠敓閿欒鏃朵笉鏇存柊鏈�鍚庢墽琛屾棩鏈燂紝浠ヤ究閲嶈瘯
                 }
             }
         }
+
+        // 15澶╂墽琛屼竴娆℃槦鏈熷ぉ2鐐�
+        public void CheckAndManageFileSize()
+        {
+            // 妫�鏌ユ槸鍚︾鍚堟墽琛屾潯浠讹細鏄熸湡澶┿��2鐐瑰乏鍙炽�佽窛绂讳笂娆℃墽琛岃嚦灏�15澶�
+            //if (!ShouldExecuteMaintenance())
+            //{
+            //    return;
+            //}
+
+            try
+            {
+                using (var connection = new SqlConnection(ConnectionString))
+                {
+                    connection.Open();
+
+                    // 1. 澶囦唤鏁版嵁搴�
+                    BackupDatabase();
+
+                    // 2. 妫�鏌ユ暟鎹簱鏂囦欢澶у皬
+                    CheckDatabaseFileSize(connection);
+
+                    // 3. 妫�鏌ュ苟澶勭悊绱㈠紩纰庣墖
+                    CheckAndHandleIndexFragmentation(connection);
+
+                    // 4. 鏇存柊缁熻淇℃伅
+                    UpdateStatistics(connection);
+
+                    // 5. 娓呯悊鏃у浠�
+                    CleanupOldBackups();
+
+                    // 鏇存柊鏈�鍚庢鏌ユ棩鏈�
+                    lock (_fileSizeLock)
+                    {
+                        _lastFileSizeCheckDate = DateTime.Now;
+                    }
+                }
+            }
+            catch (Exception ex)
+            {
+                Console.WriteLine($"鏂囦欢鐩戞帶澶辫触: {ex.Message}");
+                throw new Exception($"鏂囦欢鐩戞帶澶辫触: {ex.Message}", ex);
+            }
+        }
+
+        public void BackupDatabase()
+        {
+            lock (_backupLock)
+            {
+                try
+                {
+                    var today = DateTime.Today;
+                    // 妫�鏌ヤ粖澶╂槸鍚﹀凡缁忓浠借繃
+                    if (_lastBackupDate.HasValue && _lastBackupDate.Value.Date == today)
+                    {
+                        return;
+                    }
+                    var timestamp = DateTime.Now.ToString("yyyyMMdd_HHmmss");
+                    var backupFileName = $"{DbName}_Full_{timestamp}.bak";
+                    var backupFilePath = Path.Combine(BackupBasePath, backupFileName);
+
+                    using (var connection = new SqlConnection(ConnectionString))
+                    {
+                        connection.Open();
+                        // 鑾峰彇鏁版嵁搴撴枃浠朵俊鎭紝璁$畻澶囦唤鏂囦欢澶у皬
+                        var dbSizeQuery = @"
+                            SELECT 
+                                SUM(size/128.0) AS TotalSizeMB,
+                                SUM(FILEPROPERTY(name, 'SpaceUsed')/128.0) AS UsedSizeMB,
+                                COUNT(*) AS FileCount
+                            FROM sys.database_files
+                            WHERE type IN (0, 1)"; // 鏁版嵁鏂囦欢鍜屾棩蹇楁枃浠�
+
+                        double totalSizeMB = 0;
+                        double usedSizeMB = 0;
+                        int fileCount = 0;
+
+                        using (var cmd = new SqlCommand(dbSizeQuery, connection))
+                        using (var reader = cmd.ExecuteReader())
+                        {
+                            if (reader.Read())
+                            {
+                                totalSizeMB = Convert.ToDouble(reader["TotalSizeMB"]);
+                                usedSizeMB = Convert.ToDouble(reader["UsedSizeMB"]);
+                                fileCount = Convert.ToInt32(reader["FileCount"]);
+                            }
+                        }
+
+
+                        // 妫�鏌ョ鐩樼┖闂存槸鍚﹁冻澶�
+                        if (!CheckDiskSpace(backupFilePath, totalSizeMB))
+                        {
+                            throw new Exception("纾佺洏绌洪棿涓嶈冻锛屾棤娉曟墽琛屽浠�");
+                        }
+
+                        // 鏋勫缓澶囦唤SQL璇彞
+                        var backupSql = BuildBackupSql(backupFilePath);
+
+                        // 鎵ц澶囦唤锛堝甫閲嶈瘯鏈哄埗锛�
+                        ExecuteBackupWithRetry(connection, backupSql, backupFilePath);
+
+                        // 楠岃瘉澶囦唤鏂囦欢
+                        if (VerifyBackup)
+                        {
+                            VerifyBackupFile(connection, backupFilePath);
+                        }
+
+                        // 鏇存柊鏈�鍚庡浠芥棩鏈�
+                        _lastBackupDate = DateTime.Now;
+
+                    }
+                }
+                catch (Exception ex)
+                {
+                    Console.WriteLine($"鏁版嵁搴撳浠藉け璐�: {ex.Message}");
+                    throw new Exception($"鏁版嵁搴撳浠藉け璐�: {ex.Message}", ex);
+                }
+            }
+        }
+
+        private bool CheckDiskSpace(string backupFilePath, double estimatedBackupSizeMB)
+        {
+            try
+            {
+                var driveInfo = new DriveInfo(Path.GetPathRoot(backupFilePath));
+                var freeSpaceMB = driveInfo.AvailableFreeSpace / (1024 * 1024);
+
+                // 闇�瑕佽嚦灏�1.5鍊嶇殑绌洪棿鏉ョ‘淇濆浠介『鍒╄繘琛�
+                var requiredSpaceMB = estimatedBackupSizeMB * 1.5;
+
+                if (freeSpaceMB < requiredSpaceMB)
+                {
+                    return false;
+                }
+
+                return true;
+            }
+            catch (Exception ex)
+            {
+                Console.WriteLine($"妫�鏌ョ鐩樼┖闂存椂鍑洪敊: {ex.Message}");
+                return false;
+            }
+        }
+
+        private string BuildBackupSql(string backupFilePath)
+        {
+            var compressionOption = UseBackupCompression ? "COMPRESSION" : "NO_COMPRESSION";
+            var verifyOption = VerifyBackup ? ", CHECKSUM" : "";
+
+            return $@"
+                BACKUP DATABASE [{DbName}]
+                TO DISK = '{backupFilePath.Replace("'", "''")}'
+                WITH {compressionOption}
+                     {verifyOption}
+                     , STATS = 5
+                     , DESCRIPTION = 'Full database backup created by automated maintenance on {DateTime.Now:yyyy-MM-dd HH:mm:ss}'
+                     , MAXTRANSFERSIZE = 4194304
+                     , BLOCKSIZE = 65536
+                     , BUFFERCOUNT = 10";
+        }
+
+        private void ExecuteBackupWithRetry(SqlConnection connection, string backupSql, string backupFilePath)
+        {
+            int retryCount = 0;
+            while (retryCount < MaxBackupRetryCount)
+            {
+                try
+                {
+
+                    using (var cmd = new SqlCommand(backupSql, connection))
+                    {
+                        cmd.CommandTimeout = BackupTimeoutSeconds;
+
+                        var rowsAffected = cmd.ExecuteNonQuery();
+                        return; // 鎴愬姛鍒欓��鍑�
+                    }
+                }
+                catch (Exception ex)
+                {
+                    retryCount++;
+
+                    if (retryCount >= MaxBackupRetryCount)
+                    {
+                        // 鍒犻櫎鍙兘鎹熷潖鐨勫浠芥枃浠�
+                        try
+                        {
+                            if (File.Exists(backupFilePath))
+                            {
+                                File.Delete(backupFilePath);
+                            }
+                        }
+                        catch { }
+
+                        throw new Exception($"澶囦唤澶辫触锛屽凡杈惧埌鏈�澶ч噸璇曟鏁�({MaxBackupRetryCount}娆�): {ex.Message}", ex);
+                    }
+
+                    Console.WriteLine($"澶囦唤澶辫触锛寋MaxBackupRetryCount - retryCount}娆¢噸璇曟満浼�: {ex.Message}");
+                    Thread.Sleep(5000); // 绛夊緟5绉掑悗閲嶈瘯
+                }
+            }
+        }
+
+        private void VerifyBackupFile(SqlConnection connection, string backupFilePath)
+        {
+            try
+            {
+
+                var verifySql = $@"
+                    RESTORE VERIFYONLY 
+                    FROM DISK = '{backupFilePath.Replace("'", "''")}'
+                    WITH CHECKSUM";
+
+                using (var cmd = new SqlCommand(verifySql, connection))
+                {
+                    cmd.CommandTimeout = 300; // 5鍒嗛挓瓒呮椂
+                    cmd.ExecuteNonQuery();
+                }
+            }
+            catch (Exception ex)
+            {
+                // 楠岃瘉澶辫触鏃跺垹闄ゅ浠芥枃浠�
+                try
+                {
+                    if (File.Exists(backupFilePath))
+                    {
+                        File.Delete(backupFilePath);
+                    }
+                }
+                catch { }
+
+                throw new Exception($"澶囦唤鏂囦欢楠岃瘉澶辫触: {ex.Message}", ex);
+            }
+        }
+
+        private void CleanupOldBackups()
+        {
+            try
+            {
+
+                if (!Directory.Exists(BackupBasePath))
+                {
+                    Console.WriteLine("澶囦唤鐩綍涓嶅瓨鍦紝璺宠繃娓呯悊");
+                    return;
+                }
+
+                var cutoffDate = DateTime.Now.AddDays(-BackupRetentionDays);
+                var backupFiles = Directory.GetFiles(BackupBasePath, $"{DbName}_Full_*.bak");
+                int deletedCount = 0;
+
+                foreach (var file in backupFiles)
+                {
+                    try
+                    {
+                        var fileInfo = new FileInfo(file);
+                        if (fileInfo.CreationTime < cutoffDate)
+                        {
+                            fileInfo.Delete();
+                            deletedCount++;
+                        }
+                    }
+                    catch (Exception ex)
+                    {
+                        Console.WriteLine($"鍒犻櫎澶囦唤鏂囦欢 {file} 鏃跺嚭閿�: {ex.Message}");
+                        // 缁х画澶勭悊鍏朵粬鏂囦欢
+                    }
+                }
+
+
+            }
+            catch (Exception ex)
+            {
+                Console.WriteLine($"娓呯悊鏃у浠芥椂鍑洪敊: {ex.Message}");
+                // 涓嶆姏鍑哄紓甯革紝閬垮厤褰卞搷涓绘祦绋�
+            }
+        }
+
+        private bool ShouldExecuteMaintenance()
+        {
+            lock (_fileSizeLock)
+            {
+                var now = DateTime.Now;
+
+                // 妫�鏌ヤ粖澶╂槸鍚︽槸鏄熸湡澶�
+                if (now.DayOfWeek != DayOfWeek.Sunday)
+                {
+                    return false;
+                }
+
+                // 妫�鏌ユ椂闂存槸鍚︽槸1鐐瑰乏鍙筹紙鍏佽1:00-1:59锛�
+                if (now.Hour != 1)
+                {
+                    return false;
+                }
+
+                // 妫�鏌ユ槸鍚﹀凡缁忔墽琛岃繃
+                if (_lastFileSizeCheckDate.HasValue)
+                {
+                    // 妫�鏌ヨ窛绂讳笂娆℃墽琛屾槸鍚︽弧瓒�15澶╅棿闅�
+                    var daysSinceLastCheck = (now - _lastFileSizeCheckDate.Value).TotalDays;
+                    if (daysSinceLastCheck < MaintenanceIntervalDays)
+                    {
+                        return false;
+                    }
+                }
+
+                return true;
+            }
+        }
+
+        private void CheckDatabaseFileSize(SqlConnection connection)
+        {
+            try
+            {
+                var sizeCheckSql = @"
+                    SELECT 
+                        name AS [鏂囦欢閫昏緫鍚峕, 
+                        physical_name AS [鐗╃悊璺緞],
+                        size/128.0 AS [褰撳墠澶у皬MB], 
+                        FILEPROPERTY(name, 'SpaceUsed')/128.0 AS [宸茬敤绌洪棿MB],
+                        size/128.0 - FILEPROPERTY(name, 'SpaceUsed')/128.0 AS [鍙敤绌洪棿MB],
+                        max_size/128.0 AS [鏈�澶уぇ灏廙B],
+                        growth/128.0 AS [澧為暱閲廙B],
+                        CASE is_percent_growth 
+                            WHEN 1 THEN '鐧惧垎姣斿闀�' 
+                            ELSE '鍥哄畾澶у皬澧為暱' 
+                        END AS [澧為暱鏂瑰紡]
+                    FROM sys.database_files 
+                    WHERE type = 0"; // 0琛ㄧず鏁版嵁鏂囦欢锛�1琛ㄧず鏃ュ織鏂囦欢
+
+                using (var command = new SqlCommand(sizeCheckSql, connection))
+                {
+                    using (var reader = command.ExecuteReader())
+                    {
+                        while (reader.Read())
+                        {
+                            string logicalName = reader["鏂囦欢閫昏緫鍚�"].ToString();
+                            double currentSizeMB = Convert.ToDouble(reader["褰撳墠澶у皬MB"]);
+                            double usedSpaceMB = Convert.ToDouble(reader["宸茬敤绌洪棿MB"]);
+                            double freeSpaceMB = Convert.ToDouble(reader["鍙敤绌洪棿MB"]);
+
+
+                            // 妫�鏌ユ槸鍚﹂渶瑕佹敹缂�
+                            if (currentSizeMB * 1024 * 1024 > MaxMdfSizeBytes)
+                            {
+                                Console.WriteLine("鏁版嵁搴撴枃浠惰秴杩�8GB锛屽紑濮嬫敹缂�...");
+                                ShrinkDatabaseFile(connection, logicalName);
+                            }
+                        }
+                    }
+                }
+            }
+            catch (Exception ex)
+            {
+                Console.WriteLine($"妫�鏌ユ暟鎹簱鏂囦欢澶у皬鏃跺嚭閿�: {ex.Message}");
+                throw;
+            }
+        }
+
+        private void ShrinkDatabaseFile(SqlConnection connection, string logicalName)
+        {
+            try
+            {
+
+                // 鏀剁缉鏁版嵁搴撴枃浠�
+                string shrinkSql = $"DBCC SHRINKFILE (N'{logicalName}', {TargetShrinkSizeMB})";
+                using (var command = new SqlCommand(shrinkSql, connection))
+                {
+                    int rowsAffected = command.ExecuteNonQuery();
+                    Console.WriteLine($"鏁版嵁搴撴枃浠舵敹缂╁畬鎴愶紝鐩爣澶у皬: {TargetShrinkSizeMB} MB");
+                }
+
+                // 閲嶆柊缁勭粐绱㈠紩浠ラ伩鍏嶆敹缂╁鑷寸殑纰庣墖
+                ReorganizeAllIndexes(connection);
+            }
+            catch (Exception ex)
+            {
+                Console.WriteLine($"鏀剁缉鏁版嵁搴撴枃浠舵椂鍑洪敊: {ex.Message}");
+                throw;
+            }
+        }
+
+        private void CheckAndHandleIndexFragmentation(SqlConnection connection)
+        {
+            try
+            {
+
+                // 鏌ヨ鎵�鏈夎〃鐨勭储寮曠鐗囩巼
+                string fragmentationSql = @"
+                    SELECT 
+                        OBJECT_NAME(ips.object_id) AS TableName,
+                        i.name AS IndexName,
+                        ips.index_type_desc AS IndexType,
+                        ips.avg_fragmentation_in_percent AS FragmentationPercent,
+                        ips.page_count AS PageCount
+                    FROM sys.dm_db_index_physical_stats(DB_ID(), NULL, NULL, NULL, 'LIMITED') ips
+                    INNER JOIN sys.indexes i ON ips.object_id = i.object_id AND ips.index_id = i.index_id
+                    WHERE ips.avg_fragmentation_in_percent > 0
+                      AND ips.index_id > 0 -- 鎺掗櫎鍫�
+                      AND ips.page_count > 100 -- 鍙鐞嗚秴杩�100椤电殑绱㈠紩
+                    ORDER BY ips.avg_fragmentation_in_percent DESC";
+
+                using (var command = new SqlCommand(fragmentationSql, connection))
+                using (var reader = command.ExecuteReader())
+                {
+                    var indexesToReorganize = new List<(string TableName, string IndexName, double Fragmentation)>();
+
+                    while (reader.Read())
+                    {
+                        string tableName = reader["TableName"].ToString();
+                        string indexName = reader["IndexName"].ToString();
+                        double fragmentation = Convert.ToDouble(reader["FragmentationPercent"]);
+                        long pageCount = Convert.ToInt64(reader["PageCount"]);
+
+                        Console.WriteLine($"琛�: {tableName}, 绱㈠紩: {indexName}, 纰庣墖鐜�: {fragmentation:F2}%, 椤垫暟: {pageCount}");
+
+                        if (fragmentation > FragmentationThreshold)
+                        {
+                            indexesToReorganize.Add((tableName, indexName, fragmentation));
+                        }
+                    }
+
+                    reader.Close(); // 鍏抽棴reader浠ユ墽琛屽悗缁懡浠�
+
+                    // 澶勭悊闇�瑕侀噸鏂扮粍缁囩殑绱㈠紩
+                    if (indexesToReorganize.Any())
+                    {
+
+                        foreach (var index in indexesToReorganize)
+                        {
+                            ReorganizeIndex(connection, index.TableName, index.IndexName);
+                        }
+                    }
+                }
+            }
+            catch (Exception ex)
+            {
+                Console.WriteLine($"妫�鏌ョ储寮曠鐗囨椂鍑洪敊: {ex.Message}");
+                throw;
+            }
+        }
+
+        private void ReorganizeIndex(SqlConnection connection, string tableName, string indexName)
+        {
+            try
+            {
+                string reorganizeSql = $"ALTER INDEX [{indexName}] ON [{tableName}] REORGANIZE";
+                using (var command = new SqlCommand(reorganizeSql, connection))
+                {
+                    command.CommandTimeout = 600; // 璁剧疆10鍒嗛挓瓒呮椂
+                    command.ExecuteNonQuery();
+                }
+            }
+            catch (Exception ex)
+            {
+                Console.WriteLine($"閲嶆柊缁勭粐绱㈠紩 {tableName}.{indexName} 鏃跺嚭閿�: {ex.Message}");
+                // 缁х画澶勭悊鍏朵粬绱㈠紩
+            }
+        }
+
+        private void ReorganizeAllIndexes(SqlConnection connection)
+        {
+            try
+            {
+                string reorganizeAllSql = @"
+                    DECLARE @TableName NVARCHAR(128)
+                    DECLARE @IndexName NVARCHAR(128)
+                    DECLARE @Sql NVARCHAR(MAX)
+                    
+                    DECLARE IndexCursor CURSOR FOR
+                    SELECT 
+                        OBJECT_NAME(i.object_id) AS TableName,
+                        i.name AS IndexName
+                    FROM sys.indexes i
+                    WHERE i.index_id > 0 -- 鎺掗櫎鍫�
+                      AND OBJECT_NAME(i.object_id) IS NOT NULL
+                    
+                    OPEN IndexCursor
+                    FETCH NEXT FROM IndexCursor INTO @TableName, @IndexName
+                    
+                    WHILE @@FETCH_STATUS = 0
+                    BEGIN
+                        SET @Sql = 'ALTER INDEX [' + @IndexName + '] ON [' + @TableName + '] REORGANIZE'
+                        BEGIN TRY
+                            EXEC sp_executesql @Sql
+                            PRINT '宸查噸鏂扮粍缁囩储寮�: ' + @TableName + '.' + @IndexName
+                        END TRY
+                        BEGIN CATCH
+                            PRINT '閲嶆柊缁勭粐绱㈠紩 ' + @TableName + '.' + @IndexName + ' 鏃跺嚭閿�: ' + ERROR_MESSAGE()
+                        END CATCH
+                        
+                        FETCH NEXT FROM IndexCursor INTO @TableName, @IndexName
+                    END
+                    
+                    CLOSE IndexCursor
+                    DEALLOCATE IndexCursor";
+
+                using (var command = new SqlCommand(reorganizeAllSql, connection))
+                {
+                    command.CommandTimeout = 1800; // 璁剧疆30鍒嗛挓瓒呮椂
+                    command.ExecuteNonQuery();
+                }
+            }
+            catch (Exception ex)
+            {
+                Console.WriteLine($"閲嶆柊缁勭粐鎵�鏈夌储寮曟椂鍑洪敊: {ex.Message}");
+                throw;
+            }
+        }
+        private void UpdateStatistics(SqlConnection connection)
+        {
+            try
+            {
+                // 鏇存柊鎵�鏈夎〃鐨勭粺璁′俊鎭�
+                string updateStatsSql = "EXEC sp_updatestats";
+                using (var command = new SqlCommand(updateStatsSql, connection))
+                {
+                    command.CommandTimeout = 600; // 璁剧疆10鍒嗛挓瓒呮椂
+                    command.ExecuteNonQuery();
+                }
+            }
+            catch (Exception ex)
+            {
+                Console.WriteLine($"鏇存柊缁熻淇℃伅鏃跺嚭閿�: {ex.Message}");
+                throw;
+            }
+        }
+        // 鎻愪緵涓�涓柟娉曚緵浠诲姟璋冨害鍣ㄨ皟鐢�
+        public void ScheduleDatabaseMaintenance()
+        {
+            try
+            {
+                // 1. 鍒犻櫎鏃ф棩蹇�
+                DeleteOldLogs();
+                // 妫�鏌ユ槸鍚︾鍚堟墽琛屾潯浠�
+                if (!ShouldExecuteMaintenance())
+                {
+                    return;
+                }
+                // 2. 妫�鏌ュ拰绠$悊鏂囦欢澶у皬
+                CheckAndManageFileSize();
+            }
+            catch (Exception ex)
+            {
+                Console.WriteLine($"鎵ц鏁版嵁搴撶淮鎶や换鍔℃椂鍑洪敊: {ex.Message}");
+                throw;
+            }
+        }
     }
 }
\ No newline at end of file

--
Gitblit v1.9.3