티스토리 뷰

반응형

Entity Framework Core 101의 3번째 강의는 ASP.NET Core Web App을 이용해서 CRUD를 하는 방법에 대한 설명입니다. 

ASP.NET Web App을 생성합니다.

ASP.NET Core Web Application을 선택합니다.

프로젝트 이름을 입력합니다.

ASP.NET Core 3.1, Web Application 프로젝트로 생성합니다.

실행하면 아래와 같은 화면이 출력됩니다.

Entity Framework Core 작업

Entity Framework Core 시작(1/5)에 있는 NuGet package 추가 방법을 이용해서 3개를 추가합니다.

Entity Framework Core 시작(2/5)에 있는 Code 생성2를 이용해서 모델과 DbContext를 생성합니다.

아래 코드를 Package Manager Console에 입력합니다.

Scaffold-DbContext "Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=ContosoPets;Integrated Security=True;ConnectRetryCount=0" Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models -Context ContosoPetsContext -DataAnnotations

생성 결과 입니다.

Web Application에서 DbContext 사용

ContosoPetsContext.cs

OnConfiguring 삭제 - UseSqlServer() 부분을 Startup.cs로 이동

 

Startup.cs

Dependency Injection을 위해서 services에 DbContext를 추가

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddRazorPages();
            services.AddDbContext<ContosoPetsContext>(options => 
                options.UseSqlServer("Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=ContosoPets;Integrated Security=True;ConnectRetryCount=0"));
        }

Products CRUD 추가(모델 이름이 Product가 아니라 Products로 만들어 졌내요)

 

Pages -> Product 폴더 추가

Product 폴더에서 마우스 오른쪽 -> Add -> Razor Pages

Model 클래스를 선택하고 DbContext를 선택하고 Add 버튼 클릭

클래스 이름이 Products라 폴더 이름을 Product로 변경했습니다. 작업하실 때 이름에 유의하세요.

 

Products 모델의 CRUD를 위한 페이지가 생성되었습니다.

Product 목록 조회

Index.cshtml 파일을 브라우저로 열어줍니다.

테이블에 들어가있던 데이터가 1개라 1개만 조회가 되었습니다.

Index.cshtml.cs

IndexModel 생성자에서 ContosoPetsContext가 Injection이 되고, 그걸 _context에 넣어주고, OnGetAsync()에서 _context.Products.ToListAsync()를 이용해서 데이터를 조회합니다.

    public class IndexModel : PageModel
    {
        private readonly ContosoPets.Ui.Models.ContosoPetsContext _context;

        public IndexModel(ContosoPets.Ui.Models.ContosoPetsContext context)
        {
            _context = context;
        }

        public IList<Products> Products { get;set; }

        public async Task OnGetAsync()
        {
            Products = await _context.Products.ToListAsync();
        }
    }

Index.cshtml

@page
@model ContosoPets.Ui.Pages.Product.IndexModel

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

<h1>Index</h1>

<p>
    <a asp-page="Create">Create New</a>
</p>
<table class="table">
    <thead>
        <tr>
            <th>
                @Html.DisplayNameFor(model => model.Products[0].Name)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.Products[0].Price)
            </th>
            <th></th>
        </tr>
    </thead>
    <tbody>
@foreach (var item in Model.Products) {
        <tr>
            <td>
                @Html.DisplayFor(modelItem => item.Name)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Price)
            </td>
            <td>
                <a asp-page="./Edit" asp-route-id="@item.Id">Edit</a> |
                <a asp-page="./Details" asp-route-id="@item.Id">Details</a> |
                <a asp-page="./Delete" asp-route-id="@item.Id">Delete</a>
            </td>
        </tr>
}
    </tbody>
</table>

Product 생성

Create.cshtml.cs

    public class CreateModel : PageModel
    {
        private readonly ContosoPets.Ui.Models.ContosoPetsContext _context;

        public CreateModel(ContosoPets.Ui.Models.ContosoPetsContext context)
        {
            _context = context;
        }

        public IActionResult OnGet()
        {
            return Page();
        }

        [BindProperty]
        public Products Products { get; set; }

        // To protect from overposting attacks, enable the specific properties you want to bind to, for
        // more details, see https://aka.ms/RazorPagesCRUD.
        public async Task<IActionResult> OnPostAsync()
        {
            if (!ModelState.IsValid)
            {
                return Page();
            }

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

            return RedirectToPage("./Index");
        }
    }

Create.cshtml

@page
@model ContosoPets.Ui.Pages.Product.CreateModel

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

<h1>Create</h1>

<h4>Products</h4>
<hr />
<div class="row">
    <div class="col-md-4">
        <form method="post">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <div class="form-group">
                <label asp-for="Products.Name" class="control-label"></label>
                <input asp-for="Products.Name" class="form-control" />
                <span asp-validation-for="Products.Name" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Products.Price" class="control-label"></label>
                <input asp-for="Products.Price" class="form-control" />
                <span asp-validation-for="Products.Price" class="text-danger"></span>
            </div>
            <div class="form-group">
                <input type="submit" value="Create" class="btn btn-primary" />
            </div>
        </form>
    </div>
</div>

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

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

Product 수정

Edit.cshtml.cs

    public class EditModel : PageModel
    {
        private readonly ContosoPets.Ui.Models.ContosoPetsContext _context;

        public EditModel(ContosoPets.Ui.Models.ContosoPetsContext context)
        {
            _context = context;
        }

        [BindProperty]
        public Products Products { get; set; }

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

            Products = await _context.Products.FirstOrDefaultAsync(m => m.Id == id);

            if (Products == null)
            {
                return NotFound();
            }
            return Page();
        }

        // To protect from overposting attacks, enable the specific properties you want to bind to, for
        // more details, see https://aka.ms/RazorPagesCRUD.
        public async Task<IActionResult> OnPostAsync()
        {
            if (!ModelState.IsValid)
            {
                return Page();
            }

            _context.Attach(Products).State = EntityState.Modified;

            try
            {
                await _context.SaveChangesAsync();
            }
            catch (DbUpdateConcurrencyException)
            {
                if (!ProductsExists(Products.Id))
                {
                    return NotFound();
                }
                else
                {
                    throw;
                }
            }

            return RedirectToPage("./Index");
        }

        private bool ProductsExists(int id)
        {
            return _context.Products.Any(e => e.Id == id);
        }
    }

Edit.cshtml

@page
@model ContosoPets.Ui.Pages.Product.EditModel

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

<h1>Edit</h1>

<h4>Products</h4>
<hr />
<div class="row">
    <div class="col-md-4">
        <form method="post">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <input type="hidden" asp-for="Products.Id" />
            <div class="form-group">
                <label asp-for="Products.Name" class="control-label"></label>
                <input asp-for="Products.Name" class="form-control" />
                <span asp-validation-for="Products.Name" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Products.Price" class="control-label"></label>
                <input asp-for="Products.Price" class="form-control" />
                <span asp-validation-for="Products.Price" class="text-danger"></span>
            </div>
            <div class="form-group">
                <input type="submit" value="Save" class="btn btn-primary" />
            </div>
        </form>
    </div>
</div>

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

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

Product 삭제

Delete.cshtml.cs

    public class DeleteModel : PageModel
    {
        private readonly ContosoPets.Ui.Models.ContosoPetsContext _context;

        public DeleteModel(ContosoPets.Ui.Models.ContosoPetsContext context)
        {
            _context = context;
        }

        [BindProperty]
        public Products Products { get; set; }

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

            Products = await _context.Products.FirstOrDefaultAsync(m => m.Id == id);

            if (Products == null)
            {
                return NotFound();
            }
            return Page();
        }

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

            Products = await _context.Products.FindAsync(id);

            if (Products != null)
            {
                _context.Products.Remove(Products);
                await _context.SaveChangesAsync();
            }

            return RedirectToPage("./Index");
        }
    }

Delete.cshtml

@page
@model ContosoPets.Ui.Pages.Product.DeleteModel

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

<h1>Delete</h1>

<h3>Are you sure you want to delete this?</h3>
<div>
    <h4>Products</h4>
    <hr />
    <dl class="row">
        <dt class="col-sm-2">
            @Html.DisplayNameFor(model => model.Products.Name)
        </dt>
        <dd class="col-sm-10">
            @Html.DisplayFor(model => model.Products.Name)
        </dd>
        <dt class="col-sm-2">
            @Html.DisplayNameFor(model => model.Products.Price)
        </dt>
        <dd class="col-sm-10">
            @Html.DisplayFor(model => model.Products.Price)
        </dd>
    </dl>
    
    <form method="post">
        <input type="hidden" asp-for="Products.Id" />
        <input type="submit" value="Delete" class="btn btn-danger" /> |
        <a asp-page="./Index">Back to List</a>
    </form>
</div>

 

간단하게 Web Application을 이용한 Rest API 생성방법에 대해서 알아보았습니다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

반응형

'Entity Framework Core' 카테고리의 다른 글

Entity Framework Core 시작(5/5)  (2) 2021.01.07
Entity Framework Core 시작(4/5)  (0) 2020.12.30
SQL Sever Express vs SQLite  (0) 2020.12.27
Entity Framework Core 시작(2/5)  (2) 2020.12.19
Entity Framework Core 시작(1/5)  (0) 2020.12.16
댓글