# 🔄 Post-Migration Data Transformation ## تغییرات اعمال شده ### 1. اضافه شدن SQL Script **فایل**: `Scripts/PostMigration_DataTransformation.sql` این اسکریپت **بعد از migration داده‌ها** اجرا می‌شود و تبدیلات زیر را انجام می‌دهد: #### تبدیل Users Table: `ParentId` → `NetworkParentId + LegPosition` **مراحل:** 1. **Validation**: بررسی کاربرانی که بیشتر از 2 فرزند دارند (❌ برای binary tree نامعتبر) 2. **Copy**: کپی `ParentId` به `NetworkParentId` 3. **Assign LegPosition**: - فرزند اول → Left (0) - فرزند دوم → Right (1) 4. **Orphan Detection**: پیدا کردن کاربرانی که Parent آنها وجود ندارد 5. **Final Validation**: تایید یکپارچگی binary tree (هر Parent حداکثر 2 فرزند) 6. **Statistics**: آمار نهایی --- ## جریان کار Migration (بروزرسانی شده) ``` 1. خواندن تنظیمات ↓ 2. اتصال به Source و Target databases ↓ 3. کشف و نگاشت جداول (Table Mappings) ↓ 4. Migration داده‌ها (Batch Processing + Retry) ↓ 5. گزارش نتایج Migration ↓ 6. ✨ Post-Migration Transformation (جدید!) ├─ اجرای Scripts/PostMigration_DataTransformation.sql ├─ تبدیل ParentId → NetworkParentId ├─ تخصیص LegPosition ├─ Validation └─ Log نتایج ↓ 7. پایان ``` --- ## تنظیمات جدید ### `appsettings.json` ```json { "MigrationSettings": { ... "RunPostMigrationTransformation": true // ✨ جدید } } ``` **گزینه‌ها:** - `true` (پیشفرض): اسکریپت تبدیل بعد از migration اجرا می‌شود - `false`: فقط migration داده‌ها انجام می‌شود (تبدیل دستی) --- ## خروجی Migration ### قبل: ``` [12:35:42 INF] === Migration Complete === [12:35:42 INF] Success: 33 tables, 50,000+ records [12:35:42 INF] Failed: 0 tables [12:35:42 INF] Duration: 00:05:27 ``` ### بعد (با Transformation): ``` [12:35:42 INF] === Migration Complete === [12:35:42 INF] Success: 33 tables, 50,000+ records [12:35:42 INF] Failed: 0 tables [12:35:42 INF] Duration: 00:05:27 [12:35:42 INF] === Starting Post-Migration Data Transformation === [12:35:43 INF] Executing post-migration transformation script... [12:35:43 INF] SQL: === Starting Post-Migration Data Transformation === [12:35:43 INF] SQL: Step 1: Validating Users for binary tree conversion... [12:35:44 INF] SQL: Step 2: Copying ParentId → NetworkParentId... [12:35:44 INF] SQL: - Updated: 1,250 users [12:35:44 INF] SQL: Step 3: Assigning LegPosition (Left/Right)... [12:35:45 INF] SQL: - Updated: 1,250 users [12:35:45 INF] SQL: Step 4: Checking for orphaned nodes... [12:35:45 INF] SQL: - No orphaned nodes found [12:35:45 INF] SQL: Step 5: Verifying binary tree integrity... [12:35:45 INF] SQL: - Binary tree integrity: OK [12:35:45 INF] SQL: Step 6: Migration Statistics: [12:35:46 INF] SQL: === Post-Migration Data Transformation Complete === [12:35:46 INF] Post-migration transformation completed successfully ``` --- ## Validation Checks ### 1. Binary Tree Violation Check اگر کاربری بیشتر از 2 فرزند داشته باشد: ``` ERROR: Cannot proceed with binary tree migration. Please resolve manually. ParentId ChildCount ChildIds -------- ---------- ---------- 12345 3 67890, 67891, 67892 ``` **راه حل دستی:** 1. تصمیم بگیرید کدام 2 فرزند در binary tree بمانند 2. فرزند سوم را به Parent دیگری منتقل کنید 3. Migration را دوباره اجرا کنید ### 2. Orphaned Nodes Detection اگر Parent کاربر وجود نداشته باشد: ``` WARNING: Found orphaned nodes (parent does not exist)! Id NetworkParentId Issue ----- --------------- ----------------------------- 99999 88888 Orphaned: Parent does not exist ``` **راه حل خودکار:** - اسکریپت این کاربران را به `NetworkParentId = NULL` تبدیل می‌کند (root level) --- ## خطاها و عیب‌یابی ### خطا: "Post-migration script not found" ``` [12:35:46 WRN] Post-migration script not found: /path/to/Scripts/PostMigration_DataTransformation.sql [12:35:46 INF] Skipping data transformation. Users table will need manual ParentId→NetworkParentId migration. ``` **راه حل:** - Script را manually اجرا کنید از SQL Server Management Studio - یا فایل را در مسیر `Scripts/` قرار دهید و دوباره اجرا کنید ### خطا: "Binary tree integrity violation" ``` ERROR: Binary tree integrity violation! Some parents have more than 2 children. ``` **راه حل:** 1. Query زیر را اجرا کنید تا والدین مشکل‌دار را ببینید: ```sql SELECT ParentId, COUNT(*) as ChildCount, STRING_AGG(CAST(Id AS VARCHAR), ', ') as ChildIds FROM [CMS].[Users] WHERE ParentId IS NOT NULL GROUP BY ParentId HAVING COUNT(*) > 2; ``` 2. فرزندان اضافی را دستی حل کنید 3. Migration را دوباره اجرا کنید --- ## غیرفعال کردن Transformation اگر می‌خواهید فقط داده‌ها migrate شوند بدون تبدیل: ```json { "MigrationSettings": { "RunPostMigrationTransformation": false } } ``` سپس می‌توانید اسکریپت را **دستی** از SSMS اجرا کنید: ```sql -- فایل: Scripts/PostMigration_DataTransformation.sql -- اجرا در: Target Database ``` --- ## آمار نهایی بعد از transformation، این آمار نمایش داده می‌شود: | Metric | Count | |--------|-------| | Total Users | 2,500 | | Users with NetworkParentId | 1,250 | | Users with LegPosition Left | 625 | | Users with LegPosition Right | 625 | | Root users (no parent) | 1,250 | --- ## تغییرات کد ### `MigrationService.cs` **متد جدید:** ```csharp private async Task RunPostMigrationTransformationAsync(string targetConn, CancellationToken cancellationToken) { // 1. خواندن SQL script // 2. اتصال به Target database // 3. اجرای script با handling PRINT messages // 4. Log کردن نتایج } ``` **Integration:** - بعد از اتمام موفق migration، اگر `RunPostMigrationTransformation = true` باشد، این متد اجرا می‌شود - اگر script یافت نشود، فقط یک warning نمایش داده می‌شود (Migration fail نمی‌شود) - اگر transformation fail شود، Migration موفق تلقی می‌شود ولی warning نمایش داده می‌شود --- ## مزایا ✅ **خودکار**: نیازی به اجرای دستی script نیست ✅ **Safe**: اگر fail شود، Migration rollback نمی‌شود ✅ **Logged**: تمام مراحل در console و file log می‌شود ✅ **Configurable**: می‌توان غیرفعال کرد ✅ **Validated**: قبل از commit، تمام validationها انجام می‌شود --- **نسخه:** 1.1 **تاریخ:** December 6, 2025 **وضعیت:** ✅ Build موفق