Files
chapter-organizer/WebApp/Services/EventDefinitionService.cs
T
poprhythm 336bbb1dec Refactor Event components for improved data handling and null safety
This commit updates the Edit.razor and EventAttributes.razor components to enhance data handling and prevent potential null reference exceptions. In Edit.razor, comments are added to clarify the tracking of related careers, ensuring that the same instances are used to avoid tracking conflicts. The EventAttributes.razor component is modified to handle null EventDefinition gracefully, preventing errors when the parameter is not set. Additionally, the EventDefinitionService is updated to ensure existing careers are retrieved with tracking, improving data consistency. These changes collectively enhance the robustness and reliability of the event management features.
2026-03-10 11:12:28 -04:00

86 lines
3.0 KiB
C#

using Core.Entities;
using Core.Utility;
using Data;
using Microsoft.EntityFrameworkCore;
namespace WebApp.Services;
/// <summary>
/// Service for handling EventDefinition-related operations
/// </summary>
public class EventDefinitionService
{
private readonly AppDbContext _context;
public EventDefinitionService(AppDbContext context)
{
_context = context;
}
/// <summary>
/// Processes and normalizes related careers for an EventDefinition.
/// Matches existing careers by normalized name (case-insensitive) or creates new ones.
/// </summary>
/// <param name="eventDefinition">The EventDefinition to process careers for</param>
public async Task ProcessRelatedCareersAsync(EventDefinition eventDefinition)
{
if (string.IsNullOrWhiteSpace(eventDefinition.RelatedCareersText))
{
eventDefinition.RelatedCareers.Clear();
return;
}
var normalizedNames = CareerNormalizer.NormalizeCareerNames(eventDefinition.RelatedCareersText).ToList();
if (!normalizedNames.Any())
{
eventDefinition.RelatedCareers.Clear();
return;
}
// Get existing careers with tracking so we use the same instances the context
// may already be tracking (e.g. from the event's RelatedCareers). Using
// AsNoTracking() would create duplicate instances and cause "another instance
// with the same key value is already being tracked".
var existingCareers = await _context.Careers
.Where(c => !string.IsNullOrWhiteSpace(c.Name))
.ToListAsync();
// Build lookup dictionary, handling potential duplicates by taking the first occurrence
var careerLookup = new Dictionary<string, Career>(StringComparer.OrdinalIgnoreCase);
foreach (var career in existingCareers)
{
var normalizedKey = CareerNormalizer.GetNormalizedKey(career.Name);
if (!careerLookup.ContainsKey(normalizedKey))
{
careerLookup[normalizedKey] = career;
}
}
var careersToAdd = new List<Career>();
foreach (var normalizedName in normalizedNames)
{
var normalizedKey = CareerNormalizer.GetNormalizedKey(normalizedName);
if (careerLookup.TryGetValue(normalizedKey, out var existingCareer))
{
// Use existing career (preserve original capitalization)
careersToAdd.Add(existingCareer);
}
else
{
// Create new career with the normalized name (preserving capitalization from input)
var newCareer = new Career { Name = normalizedName };
_context.Careers.Add(newCareer);
careersToAdd.Add(newCareer);
careerLookup[normalizedKey] = newCareer;
}
}
// Replace the collection
eventDefinition.RelatedCareers = careersToAdd;
}
}