상세 컨텐츠

본문 제목

[ASP.NET Core] Entity Framework Core (Code-First)

.NET/ASP.NET Core

by 클리엘 클리엘 2021. 11. 2. 01:34

본문

728x90

Entity Framework Core는 응용 program과 database 간 연동을 위한 것으로, 사용하는 방식에 따라 Code-First방식과 DB-First방식 2가지가 존재합니다.

 

Code-First방식은 C#으로 Code를 작성하고 해당 Code를 통해 DB에 Table을 생성해서 사용하는 방식이며 반대로 DB-First방식은 DB에 Table을 먼저 생성하고 생성된 Table의 사양에 맞춰 C# Code로 생성해 사용하는 방식입니다.

 

위 2가지 방식중에서 먼저 Code-First방식에 대해 알아보고자 합니다. Code-First방식은 C#으로 Code를 먼저 작성한다고 하였는데

 

[.NET/ASP.NET Core] - [ASP.NET Core] 의존성 주입(Dependency Injection)

 

[ASP.NET Core] 의존성 주입(Dependency Injection)

흔히 '관심사의 분리'라 하는 것으로 MVC pattern의 가장 중요한 특징 중 하나에 해당합니다. program을 이루는 각 부분의 밀접도를 최소화하여 독립성을 유지하고자 하는 개념으로 new를 통해 곧바로

lab.cliel.com

위 글에서 생성한 project를 예로 들자면 WebModel에서 Data Model로 생성한 UserLogin이 DB의 Table에 해당하는 Code입니다. 그러나 단순한 Class만으로는 Table로 생성할 수는 없고 실제 DB의 Table에 맞게 어느 정도 수정이 필요합니다.

 

우선 Field가 UserID와 UserPW 2개가 있는데 실제 Table로 비교해 보자면 UserID, UserPW 이라는 2개의 Column만 존재하는 셈이 됩니다. 따라서 사용자 정보를 다루기에는 너무 부실하므로 이름과 E-Mail을 추가하고

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WebModel.Data
{
    public class UserLogin
    {
        public string UserID { get; set; }
        public string UserPW { get; set; }
        public string UserName { get; set; }
        public string UserEmail { get; set; }
    }
}

각 Field에 Table이 생성될 수 있는 Annotation을 설정해 줍니다.

namespace WebModel.Data
{
    public class UserLogin
    {
        [Key, StringLength(20), Column(TypeName = "varchar(20)")]
        public string UserID { get; set; }
        [Required, StringLength(128), Column(TypeName = "varchar(128)")]
        public string UserPW { get; set; }
        [Required, StringLength(50), Column(TypeName = "varchar(50)")]
        public string UserName { get; set; }
        [Required, StringLength(50), Column(TypeName = "varchar(50)")]
        public string UserEmail { get; set; }
    }
}

Key는 해당 Field가 Table의 Key가 됨을 의미합니다. 또한 StringLength로 Field의 길이와 Column을 통해 Table이 생성될 때 만들어질 Type을 지정하였습니다.

 

이제 WebService Project로 넘어가 해당 Project에서 NuGet Package를 통해 Micorsoft.EntityFrameworkCore와 Microsoft.EntityFrameworkCore.SqlServer, Microsoft.EntityFrameworkCore.Tools를 설치해 줍니다. 특히 2번째의 경우에는 MS SQL Server를 DB로 사용하는 경우이고 만약 다른 DB Server를 사용한다면 해당 Server에 맞는 package를 설치해야 할 것입니다. 그리고 3번째 package는 나중에 시도해볼 migration작업 시에 사용되는 package입니다.

 

package설치가 완료되었으면 WebService에도 Microsoft.EntityFrameworkCore.Tools를 제외한 동일한 package를 설치합니다. 그리고 project에 DB folder를 생성해 TestDbContext라는 이름의 class를 같이 추가합니다.

using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WebModel.Data;

namespace WebService.DB
{
    public class TestDbContext : DbContext
    {
        public TestDbContext(DbContextOptions<TestDbContext> options) : base(options)
        {
        }

        public DbSet<UserLogin> UserLogin { get; set; }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);

            modelBuilder.Entity<UserLogin>().ToTable(name: "TB_Users");
            modelBuilder.Entity<UserLogin>().HasIndex(m => new { m.UserName });
        }
    }
}

class는 DbContext class를 상속받아 만들어지며 생성자를 통해 DbContext의 생성자를 호출하고 OnModelCreating() method를 재정의합니다.

 

OnModelCreating() method에서는 ModelBuiler의 toTable() method로 추가할 Table명을 지정하고 HasIndex()로 Table의 Index까지 설정해 주는걸 확인할 수 있습니다. 이밖에도 기본값이나 key설정, 외래 key설정 등 DB상에 설정할 수 있는 거의 모든 설정을 적용시켜줄 수 있습니다.

 

다시 WebApplication1 project에서는 appsettings.json file을 수정하여 DB접속과 관련된 문자열 설정을 추가해 줍니다.

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*",
  "ConnectionStrings": {
    "test": "Server=locahost;Database=test;User ID=sa;Password=!1234"
  }
}

그리고 Startup.cs의 ConfigureServices method에서는 위에서 설정한 정보를 포함해 DbContext로의 연결정보의 설정을 AddDbContext() method를 사용하여 적용합니다.

public void ConfigureServices(IServiceCollection services)
{
    services.AddScoped<IUserService, UserService>();
    services.AddDbContext<TestDbContext>(o => o.UseSqlServer(connectionString: Configuration.GetConnectionString("test"), sqlServerOptionsAction: m => m.MigrationsAssembly(assemblyName: "toDB")));
    services.AddControllersWithViews();
}

해당 설정에서는 Migration에 필요한 Assembly도 설정한것을 볼 수 있는데 C# Code에서 실제 DB에 Table을 생성하기 위한 Migration file이 만들어질 project를 지정하는 부분입니다. 예제에서는 이 project를 toDB라고 하였으므로 toDB라는 새로운 project를 생성합니다.

그리고 만들어진 project에 Microsoft.EntityFrameworkCore.SqlServer package를 설치하고 WebService를 참조 추가합니다. 또한 WebApplication1 project에서도 toDB project를 참조 추가합니다.

 

Visual Studio 2019에서 Package Mnager Console창을 연뒤 아래 명령을 실행합니다.

add-migration addTable -project toDB

addTable은 toDB project에서 migration에 필요한 file의 이름이며 -project option을 사용해 file이 추가될 project로 toDB project를 지정하였습니다.

 

명령을 실행한 후 아래와 같은 결과가 나온다면 성공한 것입니다.

Build started...
Build succeeded.
To undo this action, use Remove-Migration.

해당 project에 file이 생성되었는지 확인합니다.

실제 file내용은 아래와 같습니다.

using Microsoft.EntityFrameworkCore.Migrations;

namespace toDB.Migrations
{
    public partial class addTable : Migration
    {
        protected override void Up(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.CreateTable(
                name: "TB_Users",
                columns: table => new
                {
                    UserID = table.Column<string>(type: "varchar(20)", maxLength: 20, nullable: false),
                    UserPW = table.Column<string>(type: "varchar(128)", maxLength: 128, nullable: false),
                    UserName = table.Column<string>(type: "varchar(50)", maxLength: 50, nullable: false),
                    UserEmail = table.Column<string>(type: "varchar(50)", maxLength: 50, nullable: false)
                },
                constraints: table =>
                {
                    table.PrimaryKey("PK_TB_Users", x => x.UserID);
                });

            migrationBuilder.CreateIndex(
                name: "IX_TB_Users_UserName",
                table: "TB_Users",
                column: "UserName");
        }

        protected override void Down(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.DropTable(
                name: "TB_Users");
        }
    }
}

위 file에서 설정된 내용대로 DB에 Table을 생성할 것입니다.

 

명령이 잘 실행되었다면 다시 아래 명령을 내려 지정된 DB에 Table을 생성하도록 합니다.

update-database -project toDB

명령에서는 migration file을 가지고 있는 project가 toDB이므로 당연히 toDB project가 지정하였습니다.

 

명령을 실행하고 아래와 같은 결과가 나온다면 정상적으로 처리된 것입니다.

Build started...
Build succeeded.
Done.

실제 DB를 확인해 보면 작성된 Table이 생성되어 있음을 확인할 수 있습니다.

 

728x90

관련글 더보기

댓글 영역