본문 바로가기
Entity Framework Core

.NET Core MVC] EF Core - 6.related data CRUD

by Fastlane 2023. 8. 28.
728x90
반응형

related data CRUD를 구현하기 위해, 아래 view파일을 포함한 CRUD 기능에 필요한 코드를 작성해보자. 

 

Index.cshtml

Create.cshtml

Delete.cstml

우선 Course Entity를 확인해보자. 

Navigation Property가 3개가 있지만, 수정은 Department만 할 수 있도록 작성하였다. 

namespace WEB.Models;


public class Course
{
        [DatabaseGenerated(DatabaseGeneratedOption.None)]
        [Display(Name = "Number")]
        public int CourseID { get; set; }

        [StringLength(50, MinimumLength = 3)]
        public string Title { get; set; }

        [Range(0, 5)]
        public int Credits { get; set; }

        public int DepartmentID { get; set; }

        //Navigation Property
        public Department? Department { get; set; }
        public ICollection<Enrollment>? Enrollments { get; set; }
        public ICollection<CourseAssignment>? CourseAssignments { get; set; }
}

CoursesController.cs

using System.Diagnostics;
using Microsoft.AspNetCore.Mvc;
using WEB.Data;
using WEB.Models;
using WEB.Models.SchoolViewModels;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Mvc.Rendering;


namespace WEB.Controllers;


public class CoursesController : Controller
{
    private readonly ILogger<HomeController> _logger;
    private readonly SchoolContext _context;


    public CoursesController(SchoolContext context, ILogger<HomeController> logger)
    {
        _logger = logger;
        _context = context;
    }


    public async Task<IActionResult> Index()
    {
        var courses = _context.Courses
            .Include(c => c.Department)
            .AsNoTracking();


        return View(await courses.ToListAsync());
    }


    public IActionResult Create()
    {
        PopulateDepartmentsDropDownList();
        return View();
    }


    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Create([Bind("CourseID,Credits,DepartmentID,Title")] Course course)
    {
        if (ModelState.IsValid)
        {
            _context.Add(course);
            await _context.SaveChangesAsync();
            return RedirectToAction(nameof(Index));
        }
        PopulateDepartmentsDropDownList(course.DepartmentID);
        return View(course);
    }


    public async Task<IActionResult> Edit(int? id)
    {
        if (id == null)
        {
            return NotFound();
        }

        var course = await _context.Courses
            .AsNoTracking()
            .FirstOrDefaultAsync(m => m.CourseID == id);

        if (course == null)
        {
            return NotFound();
        }
        PopulateDepartmentsDropDownList(course.DepartmentID);
        return View(course);
    }


    [HttpPost, ActionName("Edit")]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> EditPost(int? id)
    {
        if (id == null)
        {
            return NotFound();
        }

        var courseToUpdate = await _context.Courses
            .FirstOrDefaultAsync(c => c.CourseID == id);


        if (await TryUpdateModelAsync<Course>(courseToUpdate,
            "",
            c => c.Credits, c => c.DepartmentID, c => c.Title))
        {
            try
            {
                await _context.SaveChangesAsync();
            }
            catch (DbUpdateException /* ex */)
            {
                //Log the error (uncomment ex variable name and write a log.)
                ModelState.AddModelError("", "Unable to save changes. " +
                    "Try again, and if the problem persists, " +
                    "see your system administrator.");
            }
            return RedirectToAction(nameof(Index));
        }
        PopulateDepartmentsDropDownList(courseToUpdate.DepartmentID);
        return View(courseToUpdate);
    }


    private void PopulateDepartmentsDropDownList(object selectedDepartment = null)
    {
        var departmentsQuery = from d in _context.Departments
                                orderby d.Name
                                select d;

        ViewBag.DepartmentID = new SelectList(departmentsQuery.AsNoTracking(), "DepartmentID", "Name", selectedDepartment);
    }


    public async Task<IActionResult> Details(int? id)
    {
        if (id == null)
        {
            return NotFound();
        }

        var course = await _context.Courses
            .Include(c => c.Department)
            .AsNoTracking()
            .FirstOrDefaultAsync(m => m.CourseID == id);
       
        if (course == null)
        {
            return NotFound();
        }

        return View(course);
    }


    public async Task<ActionResult> Delete(int? id)
    {
        if (id == null)
        {
            return NotFound();
        }

        var course = await _context.Courses
            .Include(c => c.Department)
            .AsNoTracking()
            .FirstOrDefaultAsync(m => m.CourseID == id);
        if (course == null)
        {
            return NotFound();
        }
        return View(course);
    }


    [HttpPost, ActionName("Delete")]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> DeleteConfirmed(int id)
    {
        var course = await _context.Courses.FindAsync(id);
        if (course == null)
        {
            return NotFound();
        }
        _context.Courses.Remove(course);
        await _context.SaveChangesAsync();
        return RedirectToAction(nameof(Index));
    }

}

Create.cshtml

@model WEB.Models.Course

@{
    ViewData["Title"] = "Create";
}

<h1>Create</h1>

<h4>Course</h4>
<hr />
<div class="row">
    <div class="col-md-4">
        <form asp-action="Create">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <div class="form-group">
                <label asp-for="CourseID" class="control-label"></label>
                <input asp-for="CourseID" class="form-control" />
                <span asp-validation-for="CourseID" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Title" class="control-label"></label>
                <input asp-for="Title" class="form-control" />
                <span asp-validation-for="Title" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Credits" class="control-label"></label>
                <input asp-for="Credits" class="form-control" />
                <span asp-validation-for="Credits" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Department" class="control-label"></label>
                <select asp-for="DepartmentID" class="form-control" asp-items="ViewBag.DepartmentID">
                    <option value="">-- Select Department --</option>
                </select>
                <span asp-validation-for="DepartmentID" class="text-danger" />
            </div>
            <div class="form-group">
                <input type="submit" value="Create" class="btn btn-primary" />
            </div>
        </form>
    </div>
</div>


<div>
    <a asp-action="Index">Back to List</a>
</div>


@section Scripts {
    @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}

Delete.cshtml

@model WEB.Models.Course


@{
    ViewData["Title"] = "Delete";
}


<h1>Delete</h1>


<h3>Are you sure you want to delete this?</h3>
<div>
    <h4>Course</h4>
    <hr />
    <dl class="row">
        <dt class="col-sm-2">
            @Html.DisplayNameFor(model => model.CourseID)
        </dt>
        <dd class="col-sm-10">
            @Html.DisplayFor(model => model.CourseID)
        </dd>
        <dt class="col-sm-2">
            @Html.DisplayNameFor(model => model.Title)
        </dt>
        <dd class="col-sm-10">
            @Html.DisplayFor(model => model.Title)
        </dd>
        <dt class="col-sm-2">
            @Html.DisplayNameFor(model => model.Credits)
        </dt>
        <dd class="col-sm-10">
            @Html.DisplayFor(model => model.Credits)
        </dd>
        <dt class="col-sm-2">
            @Html.DisplayNameFor(model => model.Department)
        </dt>
        <dd class="col-sm-10">
            @Html.DisplayFor(model => model.Department.DepartmentID)
        </dd>
    </dl>
   
    <form asp-action="Delete">
        <input type="hidden" asp-for="CourseID" />
        <input type="submit" value="Delete" class="btn btn-danger" /> |
        <a asp-action="Index">Back to List</a>
    </form>
</div>

Details.cshtml

@model WEB.Models.Course


@{
    ViewData["Title"] = "Details";
}


<h1>Details</h1>


<div>
    <h4>Course</h4>
    <hr />
    <dl class="row">
        <dt class="col-sm-2">
            @Html.DisplayNameFor(model => model.CourseID)
        </dt>
        <dd class="col-sm-10">
            @Html.DisplayFor(model => model.CourseID)
        </dd>
        <dt class="col-sm-2">
            @Html.DisplayNameFor(model => model.Title)
        </dt>
        <dd class="col-sm-10">
            @Html.DisplayFor(model => model.Title)
        </dd>
        <dt class="col-sm-2">
            @Html.DisplayNameFor(model => model.Credits)
        </dt>
        <dd class="col-sm-10">
            @Html.DisplayFor(model => model.Credits)
        </dd>
        <dt class="col-sm-2">
            @Html.DisplayNameFor(model => model.Department)
        </dt>
        <dd class="col-sm-10">
            @Html.DisplayFor(model => model.Department.DepartmentID)
        </dd>
    </dl>
</div>
<div>
    <a asp-action="Edit" asp-route-id="@Model.CourseID">Edit</a> |
    <a asp-action="Index">Back to List</a>
</div>

Edit.cshtml

@model WEB.Models.Course


@{
    ViewData["Title"] = "Edit";
}


<h1>Edit</h1>


<h4>Course</h4>
<hr />
<div class="row">
    <div class="col-md-4">
        <form asp-action="Edit">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <input type="hidden" asp-for="CourseID" />
            <div class="form-group">
                <label asp-for="CourseID" class="control-label"></label>
                <div>@Html.DisplayFor(model => model.CourseID)</div>
            </div>
            <div class="form-group">
                <label asp-for="Title" class="control-label"></label>
                <input asp-for="Title" class="form-control" />
                <span asp-validation-for="Title" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Credits" class="control-label"></label>
                <input asp-for="Credits" class="form-control" />
                <span asp-validation-for="Credits" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Department" class="control-label"></label>
                <select asp-for="DepartmentID" class="form-control" asp-items="ViewBag.DepartmentID">
                    <option value="">-- Select Department --</option>
                </select>
                <span asp-validation-for="DepartmentID" class="text-danger" />
            </div>
            <div class="form-group">
                <input type="submit" value="Save" class="btn btn-primary" />
            </div>
        </form>
    </div>
</div>


<div>
    <a asp-action="Index">Back to List</a>
</div>


@section Scripts {
    @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}

Index.cshtml

@model IEnumerable<WEB.Models.Course>


@{
    ViewData["Title"] = "Courses";
}


<h2>Courses</h2>


<p>
    <a asp-action="Create">Create New</a>
</p>
<table class="table">
    <thead>
        <tr>
            <th>
                @Html.DisplayNameFor(model => model.CourseID)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.Title)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.Credits)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.Department)
            </th>
            <th></th>
        </tr>
    </thead>
    <tbody>
        @foreach (var item in Model)
        {
            <tr>
                <td>
                    @Html.DisplayFor(modelItem => item.CourseID)
                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.Title)
                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.Credits)
                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.Department.Name)
                </td>
                <td>
                    <a asp-action="Edit" asp-route-id="@item.CourseID">Edit</a> |
                    <a asp-action="Details" asp-route-id="@item.CourseID">Details</a> |
                    <a asp-action="Delete" asp-route-id="@item.CourseID">Delete</a>
                </td>
            </tr>
        }
    </tbody>
</table>
728x90
반응형

댓글