본문 바로가기
C#

[CSharp] c# #2 kioskProject - CRUD, ORM

by haheehee 2023. 8. 31.
728x90

Tutorial: Create a minimal API with ASP.NET Core

How to use OpenAPI in Minimal API apps

  • entity framework cross database engine

  • c\Workspace 폴더에서 cmd 창
    • code . → visual studio code 열어줌.
  • mkdir kioskProject cd kioskProject ls cd kiosk ls code .
  • Program.cs → dotnet의 기본 MVC 기반 (ASP.NET 서버 구성, API 서버 구성과 비슷)
    • app.MapGet(...) → Restful, Endpoint
  • Ctrl+J로 터미널 열고,
    • dotnet run으로 나온 주소로 열면 실행
  • dotnet build dotnet run

Restful API를 설계하는 방식

  • CRUD
    • app.***MapGet***("/menus", () => "blah blah");
      • 여기서 "/menus"(경로)가 entity, domain
    • app.***MapPost***("/menus", () => "blah blah");
    • app.***MapPut***("/menus", () => "blah blah");
    • app.***MapDelete***("/menus", () => "blah blah");
  • 나아가 새로운 방식
  • set(세트)씩 CRUD 만들기
    • app.MapGet(***"/menus"***, () => "blah blah");
    • app.MapGet(***"/cart"***, () => "blah blah");
    • app.MapGet(***"/order"***, () => "blah blah");
    • app.MapGet(***"/user"***, () => "blah blah");
      • domain에 따른 CRUD. → frontend에서 해당 도메인에 CRUD를 날려주면 된다.

 ✔️ select → app.MapGet

✔️ insert → app.MapPost

✔️ update → app.MapPut

 


  • Add NuGet packages
    • Ctrl+J로 터미널 열어서
    • dotnet add package Microsoft.EntityFrameworkCore.InMemory dotnet add package Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore

  • ORM(Object Relational Mapping) 객체-관계 매핑
    • 객체와 관계형 데이터베이스의 데이터를 자동으로 매핑(연결)해주는 것
      • 객체 지향 프로그래밍은 클래스를 사용하고, 관계형 데이터베이스는 테이블을 사용
      • 객체 모델과 관계형 모델 간에 불일치가 존재
      • ORM을 통해 객체 간의 관계를 바탕으로 SQL을 자동으로 생성하여 불일치를 해결
    • 데이터베이스 데이터 <—매핑—> Object 필드
      • 객체를 통해 간접적으로 데이터베이스 데이터를 다룸
    • Persistant API라고도 할 수 있음
    • 영속성(Persistence)
      • 데이터를 생성한 프로그램이 종료되더라도 사라지지 않는 데이터의 특성
      • Persistence Framework는 SQL Mapper와 ORM으로 나눌 수 있음
    • ORM을 이용하면 SQL Query가 아닌 직관적인 코드(메서드)로 데이터를 조작할 수 있음
    • [DB] ORM이란 - Heee's Development Blog
    ⇒ ORM이 주는 가장 큰 장점 : Entity Framework를 쓰는 이유 → db를 직접 구축하지 않아도 됨!
    • code first → 데이터를 넣기 전에 코드 먼저(class) 작성
    • database first
  • → 코드레벨에서

  • Program.cs에서
    • async를 왜 넣느냐?
      • 혹시나 모를 상황에서 내가 선점해야할 thread를 thread pool로 보내줘 효율적으로 쓰기 위함.
      • 중간에 복잡/긴 서비스가 thread를 묶어 놓음 → 비효율적이다. async로 thread를 잠시 빼서 다른 서비스가 사용할 수 있도록 하는 것이 좋다.
    • async await은 보통 다른 서버에 요청하는 것들에 사용. (예를 들어 DB!)
      • SaveChanges()를 await dbContext.SaveChangesAsync();

  • 실습
    • Dtos, Models, Persistant 폴더를 각각 만들어주기
    • DTO**(Data Transfer Object)는 VO(Value Object)**와 비슷하지
      • DTO : 순수하게 데이터를 담아 계층 간으로 전달하는 객체
      • 로직을 갖고 있지 않은 순수한 데이터 객체이며 메서드로는 getter/setter 만을 갖음
      • VO : 값 그 자체를 나타내는 객체
      • DTO와 반대로 로직을 포함할 수 있으며, VO의 경우 특정 값 자체를 표현하기 때문에 불변성의 보장을 위해 생성자를 사용하여야함

  • Program.cs
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;

var builder = WebApplication.CreateBuilder(args);
// 빌드 옵션

// Middle Ware 구성
builder.Services.AddDbContext<KioskDbContext>(opt => opt.UseInMemoryDatabase("KIOSK_DB"));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();

var app = builder.Build();

app.MapGet("/", () => "Hello Kiosk!");  // 루트로부터 라우팅("Hello World!")를

// 비동기화 // 왜? -> thread를 효율적으로 사용하기 위하여
// 필요한 context를 초기화해서 넣어줌. -> dependency injection(DI)
app.MapGet("/menus", async (KioskDbContext dbContext) => 
{
    // add, remove, load ...
    return await dbContext.Menus.ToListAsync(); //select쿼리를 준 것과 같음
});

// post는 insert query
// 여기도 마찬가지로 dbContext를 injection 받는 것
// api를 노출시킬 parameter를 Dto로 하기위함
app.MapPost("/menus", (KioskDbContext dbContext, MenuDto dto) => {
    var newMenu = new Menu 
    {
        MenuId = 1,
        Category= dto.Category,
        Name = dto.Name
    };
    dbContext.Menus.Add(newMenu);

    // 실제 데이터베이스에 리턴
    dbContext.SaveChanges();

    return newMenu;
});

app.Run();

// builder.Services.AddEndpointsApiExplorer();

// builder.Services.AddSwaggerGen();

  • var app = builder.Build(); 전에 빌드 옵션을 넣어줌
    • Middle Ware 구성
    • 나의 application이 이렇게 db를 활용하겠다.
  • app.MapGet("/", () => "Hello Kiosk!");
    • 루트로부터 ("Hello World!")를 라우팅
      • 라우팅 : 네트워크에서 경로를 선택하는 프로세스
  • app.MapGet 에서 async await을 사용하는 이유
    • 비동기화 왜? -> thread를 효율적으로 사용하기 위하여
    • 필요한 context를 초기화해서 넣어줌. → dependency injection(DI) 의존성주입
  • dbContext.SaveChanges(); → 실제 데이터베이스에 리턴

  • MenuDto.cs (Dtos폴더)
public class MenuDto {
    public string Name { get; set; }
    public string Category { get; set; }
}

- getter와 setter로 이루어진 순수하게 데이터를 담아 계층 간으로 전달하는 객체

 

  • Menu.cs (Models폴더)
public class Menu 
{
    // entity 클래스 설계
    public int MenuId { get; set; }
    public string Name { get; set; }
    public string Category { get; set; }
}

 

 

  • KioskDbContext.cs (Persistant폴더)
using Microsoft.EntityFrameworkCore;

public class KioskDbContext : DbContext // 데이터베이스를 코드레벨에서 정의하고 관리하는 클래스
{
    public KioskDbContext(DbContextOptions<KioskDbContext> options) : base(options) 
    {
        // 생성자
    }

    // 테이블
    // entity 클래스
    public DbSet<Menu> Menus { get; set; }
}

https://hhahee.notion.site/kioskProject-CRUD-ORM-7d34f62cd3714970ab00a21d3ee90862?pvs=4 

 

결과보기

 

kioskProject - CRUD, ORM

entity framework cross database engine

hhahee.notion.site

 

728x90

댓글