Files
CMS/docs/migration-network-parent-guide.md

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:

  1. Find Users: یافتن کاربران با ParentId != NULL و NetworkParentId == NULL
  2. Group by Parent: گروه‌بندی بر اساس ParentId
  3. Check Constraint: اگر Parent بیش از 2 فرزند دارد، فقط 2 تا اول را بگیر
  4. Assign Values:
    child.NetworkParentId = parentId;
    child.LegPosition = (i == 0) ? NetworkLeg.Left : NetworkLeg.Right;
    
  5. 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 کامل انجام شده؟

  • 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 پیدا کردید:

  1. Log های Seeder را بررسی کنید
  2. ValidationErrors را چک کنید
  3. SQL Script را به صورت دستی اجرا کنید