🥪 Blazor 미니 프로젝트
지난 시간에는 이전에 만들었던 RankingApp 프로젝트에 CRUD 기능 중 하나인 Create를 구현해보았다. 이번 시간에는 CRUD 중 남은 U/D인 Update, Delete를 직접 구현하는 시간을 가져보도록 하자.
🌅 RankingApp #4 Update/Delete
Entity와 Blazor를 통한 DB 연결이 무척 쉽기 때문에 이럴꺼면 SQL을 왜 배웠나 싶다. 하지만 그렇게 생각하면 오산이다. 왜냐하면 항상 ORM을 사용하는 것이 아니기 때문이다. C# 같은 경우 엔티티 프레임워크가 존재하기 때문에 사용할 수 있지만, C++의 경우 ORM을 딱히 사용하지 않아 이전과 같이 한땀한땀 처리해야 한다.
물론 C++에서도 일일히 다 노가다로 만들어 전송하는 건 너무 오래걸리기 때문에 SQL의 Stored Procedure 기능인 SP 기능을 통해 데이터베이스에 함수를 등록하여 어떤 SQL이 호출될지를 미리 등록할 수 있다. 사담은 그만두고 Update 기능 먼저 추가해보도록 하자.
먼저 랭킹을 나타내는 레이저 컴포넌트의 Update와 Delete 버튼을 추가해야 한다. 다음과 같이 기존의 table에서 각각의 버튼을 추가하는 로직을 만들어 주도록 하자.
@page "/ranking"
...
<AuthorizeView>
@* 인증 받은 사용자 *@
<Authorized>
@if (_gameResults == null)
{
<p><em>Loading...</em></p>
}
else
{
<table class="table">
<thead>
<tr>
<th>UsersName</th>
<th>Score</th>
<th>Date</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var gameResult in _gameResults)
{
<tr>
<td>@gameResult.UserName</td>
<td>@gameResult.Score</td>
<td>@gameResult.Date.ToString()</td>
<td>
<button class="btn btn-primary" @onclick=" () => UpdateGameResult(gameResult)">Edit</button>
</td>
<td>
<button class="btn btn-primary" @onclick=" () => DeleteGameResult(gameResult)">Delete</button>
</td>
</tr>
}
</tbody>
</table>
...
}
</Authorized>
</AuthorizeView>
@code {
List<GameResult> _gameResults;
}
이 떄 @onclick의 함수는 인자를 받을 수 없으므로 람다식을 이용해 버튼의 기능을 구현하도록 하자. 위와 같이 작성했으면 이제 UpdateGameResult 함수와 DeleteGameResult 함수를 밑에서 구현하도록 하자.
@page "/ranking"
...
@code {
List<GameResult> _gameResults;
...
void UpdateGameResult(GameResult gameResult)
{
_showPopup = true;
_gameResult = gameResult;
}
async Task SaveGameResult()
{
if (_gameResult.Id == 0)
{
_gameResult.Date = DateTime.Now;
var result = RankingService.AddGameResult(_gameResult);
}
else
{
var result = RankingService.UpdateGameResult(_gameResult);
}
_showPopup = false;
// 데이터 갱신
_gameResults = await RankingService.GetGameResultsAsync();
}
}
Update의 경우 지난 시간의 SaveGameResult의 ID를 비교하는 부분의 Id 값이 0이 아닐경우인 if-else 조건문의 else에 해당하여 RankingService에서 UpdateGameResult 로직 처리를 해 줄 것이다. RankingService로 돌아가서 UpdateGameResult의 함수를 구현해주도록 하자.
using RankingApp.Data.Models;
namespace RankingApp.Data.Services
{
public class RankingService
{
ApplicationDbContext _context;
public RankingService(ApplicationDbContext context)
{
_context = context;
}
// CREATE
...
// READ
...
// UPDATE
public Task<bool> UpdateGameResult(GameResult gameResult)
{
var findResult = _context.GameResults
.Where(x => x.Id == gameResult.Id)
.FirstOrDefault();
if (findResult == null)
{
return Task.FromResult(false);
}
findResult.UserName = gameResult.UserName;
findResult.Score = gameResult.Score;
// DB 동기화
_context.SaveChanges();
// 성공 반환
return Task.FromResult(true);
}
// DELETE
...
}
}
_context와 링큐를 이용하여 인자값으로 받은 gameResult의 Id와 현재 Db에 있는 Id를 비교하여 값을 찾아준다. 만약 해당 값이 null이라면 존재하지 않기 때문에 bool 반환 값을 false로 처리한다. 그렇지 않은 경우 데이터를 찾은 것이기 때문에 findResult(=기존 값)의 값을 인자 값으로 들어온 gameResult의 UserName과 Score로 변경해주도록 한다.
마지막으로 SaveChange를 통해 Db를 동기화 시켜주고, bool 반환 값을 true로 처리하여 해당 함수가 성공적으로 동작했다는 것을 반환하여 처리해주도록 하자. 다음으로는 Delete를 구현하도록 하자.
@page "/ranking"
...
@code {
List<GameResult> _gameResults;
...
void UpdateGameResult(GameResult gameResult)
{
_showPopup = true;
_gameResult = gameResult;
}
async Task DeleteGameResult(GameResult gameResult)
{
var result = RankingService.DeleteGameResult(gameResult);
// 데이터 갱신
_gameResults = await RankingService.GetGameResultsAsync();
}
}
DeleteGameResult 함수는 별다른 내용없이 RankingService의 DeleteGameResult 함수를 처리하는 로직으로 구현하도록 한다. 이 후 데이터 갱신을 위해 _gameResults를 DB에서 모조리 긁어와 갱신처리 한다. 마찬가지로 RankingService에서 DeleteGameResult 내용을 구현하도록 하자.
using RankingApp.Data.Models;
namespace RankingApp.Data.Services
{
public class RankingService
{
ApplicationDbContext _context;
public RankingService(ApplicationDbContext context)
{
_context = context;
}
...
// UPDATE
public Task<bool> UpdateGameResult(GameResult gameResult)
{
var findResult = _context.GameResults
.Where(x => x.Id == gameResult.Id)
.FirstOrDefault();
if (findResult == null)
{
return Task.FromResult(false);
}
findResult.UserName = gameResult.UserName;
findResult.Score = gameResult.Score;
// DB 동기화
_context.SaveChanges();
// 성공 반환
return Task.FromResult(true);
}
// DELETE
public Task<bool> DeleteGameResult(GameResult gameResult)
{
var findResult = _context.GameResults
.Where(x => x.Id == gameResult.Id)
.FirstOrDefault();
if (findResult == null)
{
return Task.FromResult(false);
}
_context.GameResults.Remove(gameResult);
// DB 동기화
_context.SaveChanges();
// 성공 반환
return Task.FromResult(true);
}
}
}
Delete 또한 Update 처럼 어려운 것 없이, 인자값으로 들어온 gameResult의 Id 값을 검사하여 해당 값이 존재할 경우 Remove 처리만 해주면 된다. 이 상태에서 빌드하여 정상 작동하는지 확인해보도록 하자.
이렇게 해서 Blazor를 통한 RankingApp CRUD를 모두 진행해보았다. 다음으로는 Unity와 Blazor를 연동하는 내용을 학습할 것인데 아쉽게도 유니티와 Blazor는 연동을 할 수 없다. 우리가 Unity를 통해 연동하는 것은 REST라고 불리는 웹 API이며 다음 시간부터는 웹 API를 학습하고 이를 통해 Unity와 WebApi를 연동하는 시간을 가져보도록 하자. 😎
'공부 > 인프런 - Rookiss' 카테고리의 다른 글
Part 6-7-2. WebAPI와 REST 서비스 : WebApi #2 (0) | 2024.10.13 |
---|---|
Part 6-7-1. WebAPI와 REST 서비스 : WebApi #1 (2) | 2024.10.11 |
Part 6-6-3. Blazor 미니 프로젝트 : Blazor RankingApp #3 (3) | 2024.10.07 |
Part 6-6-2. Blazor 미니 프로젝트 : Blazor RankingApp #2 (5) | 2024.10.01 |
Part 6-6-1. Blazor 미니 프로젝트 : Blazor RankingApp #1 (2) | 2024.09.30 |