Search code examples
entity-frameworkasp.net-coreone-to-manyrazor-pages

In ASP.NET Core 6, how do I add an object to a collection navigation property of another object and save the changes in the database?


I'm still relatively new to using .NET with one-to-many-relationships. I'm trying to build a simple school management web app. So far I only have two models, one for districts and one for schools.

public class District
{
    public int DistrictId { get; set; }
    public string Name { get; set; } = string.Empty;
    public List<School> Schools { get; set; } = new List<School>();
}

public class School
{
    public int SchoolId { get; set; }
    public string Name { get; set; } = string.Empty;
    public int DistrictId { get; set; }
}

I've scaffolded those into CRUD pages which is all working fine. My hang up is in the OnPostAsync() method of the School/Create pagemodel. I wrote some simple code to assign the correct DistrictId to the created school and then add the new school to it's district's list of schools.

public async Task<IActionResult> OnPostAsync()
    {
        var DistrictName = Request.Form["DistrictName"];

        if (!ModelState.IsValid || _context.School == null || School == null)
        {
            return Page();
        }

        foreach (District district in _context.District)
        {
            if (district.Name == DistrictName)
            {
                School.DistrictId = district.DistrictId;
                district.Schools.Add(School);
                break;
            }
        }

        _context.School.Add(School);
        await _context.SaveChangesAsync();

        return RedirectToPage("./Index");
    }

I set some breakpoints and stepped through the method and I can see that the school is getting added to the district's list correctly. However, SaveChangesAsync() doesn't actually seem to be saving it, because when I try to view the list on the District/Details page it's empty again. I did some reading on entity states and I still feel like that might be the issue, but I wasn't able to find a solution that would save the changes. Any help would be really appreciated!


Solution

  • Try to add below code in your School class.

    public District District {get;set;} 
    

    result:

    enter image description here

    Add Include(x=>x.Schools) in your code like below:

    District = await _context.District.Include(x=>x.Schools).FirstOrDefaultAsync(m => m.DistrictId == id);
    

    in your cshtml:

    <dt class="col-sm-2">
                @Html.DisplayNameFor(model => model.District.Schools)
            </dt>
           
                @foreach (var school in Model.District.Schools)
                {
                <dd class="col-sm-10"> @school.Name </dd>
            }
    

    result:

    enter image description here