6.2 KiB
6.2 KiB
🔄 Migration Guide: ParentId → NetworkParentId
📋 Overview
در سیستم قدیمی، کاربران با استفاده از User.ParentId به هم متصل میشدند (Parent-Child relationship).
سیستم جدید Network-Club-Commission از یک Binary Tree استفاده میکند که نیاز به:
User.NetworkParentId(شناسه پدر در شبکه باینری)User.LegPosition(Left یا Right)
برای اجرای صحیح Worker و محاسبات، باید تمام کاربران قدیمی Migrate شوند.
⚠️ Critical Issues
مشکل 1: Binary Tree Constraint
- هر Parent فقط میتواند 2 فرزند داشته باشد (Left & Right)
- اگر کاربری در سیستم قدیمی بیشتر از 2 فرزند دارد، Migration فقط 2 فرزند اول را میگیرد
مشکل 2: Orphaned Nodes
- اگر
ParentIdاشاره به یک کاربر نامعتبر (حذف شده) باشد، آن User Orphaned است - Orphaned nodes در Binary Tree نادیده گرفته میشوند
🚀 Migration Methods
روش 1: Automatic (Seeder - توصیه میشود)
Migration به صورت خودکار در Program.cs در حالت Development اجرا میشود:
// در Program.cs
var migrationSeeder = new NetworkParentIdMigrationSeeder(dbContext, logger);
await migrationSeeder.SeedAsync();
مزایا:
- ✅ Idempotent (میتوان چندین بار اجرا کرد، فقط یکبار تاثیر میگذارد)
- ✅ Validation اتوماتیک
- ✅ Logging کامل
کجا اجرا میشود؟
- فقط در Development environment
- هر بار که پروژه Run شود
روش 2: Manual (Command)
اگر نیاز به اجرای دستی دارید:
// درخواست از طریق MediatR
var result = await _mediator.Send(new MigrateNetworkParentIdCommand());
if (result.Success)
{
Console.WriteLine($"Migrated: {result.MigratedCount}");
Console.WriteLine($"Skipped: {result.SkippedCount}");
}
else
{
Console.WriteLine($"Error: {result.Message}");
}
روش 3: SQL Script
برای Production یا اجرای مستقیم روی Database:
# فایل: CMSMicroservice.Infrastructure/Migrations/Scripts/20250601_MigrateParentIdToNetworkParentId.sql
نکته مهم:
قبل از اجرا، حتماً بررسی کنید که آیا کاربری بیش از 2 فرزند دارد:
SELECT
ParentId,
COUNT(*) as ChildCount,
STRING_AGG(CAST(Id AS VARCHAR), ', ') as ChildIds
FROM Users
WHERE ParentId IS NOT NULL
GROUP BY ParentId
HAVING COUNT(*) > 2;
📊 Validation After Migration
1. بررسی تعداد کاربران Migrate شده
var stats = await _context.Users
.GroupBy(u => 1)
.Select(g => new
{
TotalUsers = g.Count(),
UsersWithNetworkParent = g.Count(u => u.NetworkParentId != null),
LeftChildren = g.Count(u => u.LegPosition == NetworkLeg.Left),
RightChildren = g.Count(u => u.LegPosition == NetworkLeg.Right)
})
.FirstOrDefaultAsync();
2. بررسی Orphaned Nodes
SELECT Id, NetworkParentId
FROM Users
WHERE NetworkParentId IS NOT NULL
AND NetworkParentId NOT IN (SELECT Id FROM Users);
3. بررسی Binary Tree Violation
SELECT NetworkParentId, COUNT(*) as ChildCount
FROM Users
WHERE NetworkParentId IS NOT NULL
GROUP BY NetworkParentId
HAVING COUNT(*) > 2;
⚙️ Algorithm Details
مراحل Migration:
- Find Users: یافتن کاربران با
ParentId != NULLوNetworkParentId == NULL - Group by Parent: گروهبندی بر اساس ParentId
- Check Constraint: اگر Parent بیش از 2 فرزند دارد، فقط 2 تا اول را بگیر
- Assign Values:
child.NetworkParentId = parentId; child.LegPosition = (i == 0) ? NetworkLeg.Left : NetworkLeg.Right; - Save & Validate: ذخیره و اعتبارسنجی Binary Tree
🐛 Troubleshooting
مشکل: Parent has more than 2 children
راه حل:
تصمیم دستی بگیرید که کدام 2 فرزند را نگه دارید:
-- بررسی کنید که کدام Parent مشکل دارد
SELECT ParentId, COUNT(*) as ChildCount
FROM Users
WHERE ParentId = 123
GROUP BY ParentId;
-- لیست فرزندان را ببینید
SELECT Id, FullName, CreatedAt
FROM Users
WHERE ParentId = 123
ORDER BY CreatedAt;
-- دستی NetworkParentId را برای 2 فرزند انتخابی Set کنید
UPDATE Users
SET NetworkParentId = 123, LegPosition = 0 -- Left
WHERE Id = 456;
UPDATE Users
SET NetworkParentId = 123, LegPosition = 1 -- Right
WHERE Id = 789;
مشکل: Orphaned Nodes (Parent doesn't exist)
راه حل:
ParentId را NULL کنید یا به یک Parent معتبر متصل کنید:
-- گزینه 1: NULL کردن (Root شدن)
UPDATE Users
SET ParentId = NULL, NetworkParentId = NULL
WHERE ParentId = 999; -- 999 وجود ندارد
-- گزینه 2: اتصال به Parent دیگر
UPDATE Users
SET ParentId = 1, NetworkParentId = 1
WHERE ParentId = 999;
✅ Checklist Before Production
- Migration در Development اجرا شده؟
- Validation Errors بررسی شد؟
- Orphaned Nodes رفع شدند؟
- Binary Tree Violations رفع شدند؟
- Backup از Database گرفته شده؟
- Migration Script برای Production آماده است؟
- Testing کامل انجام شده؟
🔗 Related Files
- Seeder:
CMSMicroservice.Infrastructure/Data/Seeding/NetworkParentIdMigrationSeeder.cs - Command:
CMSMicroservice.Application/UserCQ/Commands/MigrateNetworkParentId/ - SQL Script:
CMSMicroservice.Infrastructure/Migrations/Scripts/20250601_MigrateParentIdToNetworkParentId.sql - Entity:
CMSMicroservice.Domain/Entities/User.cs(خطوط 16, 45, 49)
📞 Support
اگر مشکل خاصی با Migration پیدا کردید:
- Log های Seeder را بررسی کنید
- ValidationErrors را چک کنید
- SQL Script را به صورت دستی اجرا کنید