у меня есть модель этапов проекта
```
    public class ProjectStage :IEntity
    {
        [Key]
        public int Id { get; set; }
        public string StageTitle { get; set; }
        public string Description { get; set; }

        [DataType(DataType.Date)]
        public DateTime StartDate { get; set; }

        [DataType(DataType.Date)]
        public DateTime EndDate { get; set; }
        public string Status { get; set; }

        // Связи
        public int ProjectId { get; set; }
        public Project Project { get; set; }
    }
и модель работ
```
    public class Work :IEntity
    {
        [Key]
        public int WorkId { get; set; }

        [Required]
        [MaxLength(50)]
        public string NumberItem { get; set; }

        [MaxLength(50)]
        public string? NodeCode { get; set; }

        [Required]
        [MaxLength(200)]
        public string? CostName { get; set; }

        public string? ISRComment { get; set; }

        public string? ContractorComment { get; set; }

        [MaxLength(50)]
        public string? UnitOfMeasure { get; set; }

        public decimal? ConsumptionCoefficient { get; set; }

        public decimal? BOCount { get; set; }

        public decimal? TotalCount { get; set; }

        public decimal? MatEquipmPrice { get; set; }

        public decimal? SmpPnpPrice { get; set; }

        public decimal? TotalPrice { get; set; }

        public decimal? MatEquipmCost { get; set; }

        public decimal? SmpPnpCost { get; set; }

        public decimal? TotalCost { get; set; }

        // Внешние ключи
        [ForeignKey("Project")]
        public int ProjectId { get; set; }

        [ForeignKey("ParentWork")]
        public int? ParentWorkId { get; set; }

        [ForeignKey("Status")]
        public int StatusId { get; set; }

        [ForeignKey("Unit")]
        public int? UnitId { get; set; }

        public int? HierarchyLevel { get; set; }

        public bool IsMigrated { get; set; }

        public DateTime? StartDate { get; set; }

        public DateTime? EndDate { get; set; }

        public string? Comment { get; set; }

        // Навигационные свойства
        public Project Project { get; set; }

        public Work ParentWork { get; set; }

        public Status Status { get; set; }

        public Unit Unit { get; set; }

        public ICollection<Work> SubWorks { get; set; } = new List<Work>();

        public ICollection<WorkMaterial> WorkMaterials { get; set; } = new List<WorkMaterial>();
    }
```
мне нужно связать эти модели. К этапу проекта будут добавляться работы.
вот контроллер который импортирует работы
```
// Services/ImportService.cs

using AutoMapper;
using BuildingFlow.Data.Contract;
using BuildingFlow.Data.Entities;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using System.Globalization;

namespace BuildingFlow.Services.CostImportService
{
    public class ImportService
    {
        private readonly IUnitOfWork _unitOfWork;
        private readonly IMapper _mapper;
        private readonly ILogger<ImportService> _logger;

        // Словари для сопоставления старых Id с новыми идентификаторами
        private readonly Dictionary<int, int> _workIdMap = new();
        private readonly Dictionary<int, int> _materialIdMap = new();

        public ImportService(IUnitOfWork unitOfWork, IMapper mapper, ILogger<ImportService> logger)
        {
            _unitOfWork = unitOfWork;
            _mapper = mapper;
            _logger = logger;
        }

        public async Task ImportCostItemsAsync()
        {
            await _unitOfWork.BeginTransactionAsync();
            try
            {
                var costItemsRepository = _unitOfWork.GetRepository<CostItem>();
                var projectsRepository = _unitOfWork.GetRepository<Project>();
                //var costTypesRepository = _unitOfWork.GetRepository<CostType>(); // Возможно, не требуется в новой схеме
                var unitsRepository = _unitOfWork.GetRepository<Unit>();
                var worksRepository = _unitOfWork.GetRepository<Work>();
                var materialsRepository = _unitOfWork.GetRepository<Material>();
                var workMaterialsRepository = _unitOfWork.GetRepository<WorkMaterial>();
                var statusesRepository = _unitOfWork.GetRepository<Status>(); // Для статусов

                // Получаем все записи из старой таблицы, отсортированные по уровню иерархии
                var costItems = await costItemsRepository.AsQueryable()
                    .OrderBy(c => c.HierarchyLevel)
                    .ToListAsync();

                foreach (var costItem in costItems)
                {
                    // Пропускаем уже импортированные записи
                    if (costItem.IsMigrated)
                    {
                        _logger.LogInformation($"Запись Id {costItem.Id} уже импортирована. Пропуск.");
                        continue;
                    }

                    try
                    {
                        // 1. Обработка Project
                        if (costItem.ProjectId == 0)
                        {
                            _logger.LogWarning($"Запись Id {costItem.Id} имеет неверный ProjectId.");
                            continue; // Пропускаем запись
                        }

                        var project = await projectsRepository.AsQueryable()
                            .FirstOrDefaultAsync(p => p.Id == costItem.ProjectId);

                        if (project == null)
                        {
                            // Создаем новый проект, если не найден
                            project = new Project
                            {
                                Id = costItem.ProjectId,
                                //ProjectName = $"Project {costItem.ProjectId}"
                                // Заполните другие поля проекта, если есть
                            };
                            projectsRepository.Create(project);
                            await _unitOfWork.SaveChangesAsync();
                            _logger.LogInformation($"Создан новый проект: {project.Id}");
                        }

                        // 2. Обработка Unit
                        Unit unit = null;
                        if (!string.IsNullOrWhiteSpace(costItem.UnitOfMeasure))
                        {
                            unit = await unitsRepository.AsQueryable()
                                .FirstOrDefaultAsync(u => u.UnitName == costItem.UnitOfMeasure);

                            if (unit == null)
                            {
                                unit = new Unit
                                {
                                    UnitName = costItem.UnitOfMeasure,
                                    UnitSymbol = costItem.UnitOfMeasure // При необходимости уточните символ
                                };
                                unitsRepository.Create(unit);
                                await _unitOfWork.SaveChangesAsync();
                                _logger.LogInformation($"Создана новая единица измерения: {unit.UnitName}");
                            }
                        }

                        // 3. Обработка статуса
                        // Предполагается, что у вас уже есть некоторые статусы, например:
                        // "Запланировано", "В процессе", "Завершено"
                        string defaultStatusName = "Запланировано"; // Или другой подходящий статус
                        var status = await statusesRepository.AsQueryable()
                            .FirstOrDefaultAsync(s => s.StatusName == defaultStatusName);

                        if (status == null)
                        {
                            status = new Status
                            {
                                StatusName = defaultStatusName
                            };
                            statusesRepository.Create(status);
                            await _unitOfWork.SaveChangesAsync();
                            _logger.LogInformation($"Создан новый статус: {status.StatusName}");
                        }

                        // 4. Обработка ParentWork
                        int? parentWorkId = null;
                        if (costItem.ParentId.HasValue)
                        {
                            if (_workIdMap.TryGetValue(costItem.ParentId.Value, out int newParentWorkId))
                            {
                                parentWorkId = newParentWorkId;
                            }
                            else
                            {
                                _logger.LogWarning($"ParentId {costItem.ParentId.Value} не найден для записи Id {costItem.Id}. Запись пропущена.");
                                continue; // Пропускаем запись
                            }
                        }

                        // 5. Создание записи Work или Material
                        if (costItem.TypeCost.Equals("Работа", StringComparison.OrdinalIgnoreCase))
                        {
                            // Создание записи Work
                            var work = new Work
                            {
                                NumberItem = costItem.NumberItem,
                                NodeCode = costItem.NodeCode,
                                CostName = costItem.CostName,
                                ISRComment = costItem.ISRComment,
                                ContractorComment = costItem.ContractorComment,
                                UnitOfMeasure = unit?.UnitName,
                                ConsumptionCoefficient = costItem.ConsumptionCoefficient,
                                BOCount = costItem.BOCount,
                                TotalCount = costItem.TotalCount,
                                MatEquipmPrice = ParseDecimal(costItem.MatEquipmPrice),
                                SmpPnpPrice = ParseDecimal(costItem.SmpPnpPrice),
                                TotalPrice = ParseDecimal(costItem.TotalPrice),
                                MatEquipmCost = ParseDecimal(costItem.MatEquipmCost),
                                SmpPnpCost = ParseDecimal(costItem.SmpPnpCost),
                                TotalCost = ParseDecimal(costItem.TotalCost),
                                ProjectId = project.Id,
                                HierarchyLevel = costItem.HierarchyLevel,
                                ParentWorkId = parentWorkId,
                                IsMigrated = costItem.IsMigrated,
                                StartDate = DateTime.Today, // При необходимости измените логику
                                EndDate = null, // При необходимости измените логику
                                StatusId = status.StatusId,
                                Comment = "Импортировано автоматически" // Или другое значение
                            };

                            worksRepository.Create(work);
                            await _unitOfWork.SaveChangesAsync();

                            _logger.LogInformation($"Создана работа: {work.CostName} (NumberItem: {work.NumberItem})");

                            // Обновление словаря
                            _workIdMap[costItem.Id] = work.WorkId;

                            // Установка флага миграции
                            costItem.IsMigrated = true;

                            await _unitOfWork.SaveChangesAsync();
                        }
                        else if (costItem.TypeCost.Equals("Материал", StringComparison.OrdinalIgnoreCase))
                        {
                            // Для материалов необходимо определить, к какой работе они относятся
                            // Предположим, что связь с работой определяется по ParentId
                            int? associatedWorkId = null;
                            if (costItem.ParentId.HasValue)
                            {
                                if (_workIdMap.TryGetValue(costItem.ParentId.Value, out int mappedWorkId))
                                {
                                    associatedWorkId = mappedWorkId;
                                }
                                else
                                {
                                    _logger.LogWarning($"ParentId {costItem.ParentId.Value} не найден для материала Id {costItem.Id}. Материал пропущен.");
                                    continue; // Пропускаем запись
                                }
                            }
                            else
                            {
                                _logger.LogWarning($"Материал Id {costItem.Id} не связан с какой-либо работой. Материал пропущен.");
                                continue; // Пропускаем запись
                            }

                            // Создание записи Material
                            var material = new Material
                            {
                                NumberItem = costItem.NumberItem,
                                NodeCode = costItem.NodeCode,
                                CostName = costItem.CostName,
                                ISRComment = costItem.ISRComment,
                                ContractorComment = costItem.ContractorComment,
                                UnitOfMeasure = unit?.UnitName,
                                ConsumptionCoefficient = costItem.ConsumptionCoefficient,
                                BOCount = costItem.BOCount,
                                TotalCount = costItem.TotalCount,
                                MatEquipmPrice = ParseDecimal(costItem.MatEquipmPrice),
                                SmpPnpPrice = ParseDecimal(costItem.SmpPnpPrice),
                                TotalPrice = ParseDecimal(costItem.TotalPrice),
                                MatEquipmCost = ParseDecimal(costItem.MatEquipmCost),
                                SmpPnpCost = ParseDecimal(costItem.SmpPnpCost),
                                TotalCost = ParseDecimal(costItem.TotalCost),
                                ProjectId = project.Id,
                                TypeCost = costItem.TypeCost,
                                IsMigrated = costItem.IsMigrated,
                                // Дополнительные поля при необходимости
                            };

                            materialsRepository.Create(material);
                            await _unitOfWork.SaveChangesAsync();

                            _logger.LogInformation($"Создан материал: {material.CostName} (NumberItem: {material.NumberItem})");

                            // Связь материала с работой через WorkMaterial
                            var workMaterial = new WorkMaterial
                            {
                                WorkId = associatedWorkId.Value,
                                MaterialId = material.MaterialId,
                                //Quantity = costItem.TotalCount ?? 0 // Уточните, какое поле использовать
                            };
                            workMaterialsRepository.Create(workMaterial);
                            await _unitOfWork.SaveChangesAsync();

                            _logger.LogInformation($"Связали материал Id {material.MaterialId} с работой Id {associatedWorkId.Value}");

                            // Обновление словаря
                            _materialIdMap[costItem.Id] = material.MaterialId;

                            // Установка флага миграции
                            costItem.IsMigrated = true;

                            await _unitOfWork.SaveChangesAsync();
                        }
                        else
                        {
                            _logger.LogWarning($"Неизвестный тип затрат '{costItem.TypeCost}' для записи Id {costItem.Id}. Запись пропущена.");
                            continue; // Пропускаем запись
                        }
                    }
                    catch (Exception ex)
                    {
                        _logger.LogError(ex, $"Ошибка при обработке записи Id {costItem.Id}");
                        // В случае ошибки можно решить, продолжать ли импорт или прерывать
                        throw; // В данном случае прерываем импорт
                    }
                }

                // Завершение транзакции
                await _unitOfWork.CommitAsync();
                _logger.LogInformation("Миграция данных завершена успешно.");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Ошибка при миграции данных. Произошёл откат транзакции.");
                await _unitOfWork.RollbackAsync();
                throw; // Перебрасываем ошибку выше, если необходимо
            }
        }

        /// <summary>
        /// Безопасный парсер для decimal, возвращает 0 если значение null или некорректно
        /// </summary>
        private decimal ParseDecimal(decimal? value)
        {
            return value ?? 0m;
        }
    }
}