데이터베이스를 사용할 때 매번 코드에서 데이터를 정의하고, DBMS에서 데이터베이스를 생성하는 작업을 여러 번 하는 것은 상당히 불편한 작업입니다.
이번에는 간단하게 EntityFramework Core 에서 Code로만 소스를 작성하고 DB를 커맨드로 생성하는 방법을 공유드리려고 합니다.
완전히 Code에서 생성하는 방법을 택할 수도 있지만, 여기에서 소개하는 방법은 Code로 데이터베이스에 들어갈 테이블 / 컬럼 등을 작성한 후에 커맨드를 입력해서 데이터베이스를 생성하고, 실제 동작하는 코드 상에서 Create Table 하는 코드는 들어가 있지는 않은 방식입니다.
실제 이 포스팅에서 공유하는 데이터는 작성일 기준 최신 LTS 버전인 .NET 8.0 과 EF Core6를 Visual Studio를 사용하는 것을 기준으로 작성되었습니다.
먼저 간단한 C# 프로젝트를 생성해봅시다.
새 프로젝트 만들기 => 콘솔 앱 템플릿 선택 => 다음 버튼 클릭 => 프로젝트 이름 입력 (TestBlog) => 다음 버튼 클릭 => .NET8.0 선택, 최상위 문 사용안함 체크 표시 => 만들기 버튼 클릭
위 과정을 통해서 TestBlog 라는 프로젝트를 생성하였습니다. 그러면 현재는 프로젝트 안에는 Program.cs 라는 파일만 있을 것이고, 특별한 종속성도 포함되어 있지 않을 것입니다.
// Program.cs
namespace TestBlog
{
internal class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello, World!");
}
}
}
여기에 새로운 파일을 생성해서 데이터베이스를 위한 간단한 Blog 모델을 추가할 수 있습니다. 일반적으로는 DbContext 라는 것과 실제 데이터베이스에 저장될 모델을 분리하는 것이 맞습니다만은 여기에서는 지면상의 이슈로 간단하게 하나의 파일 안에 모델과 컨텍스트를 동시에 선언하도록 하겠습니다.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
//Blog.cs
namespace TestBlog
{
public class BlogContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
}
public class Blog
{
public int BlogId { get; set; }
public string Name { get; set; }
}
}
이렇게 파일을 만들고나면 DbContext 와 DbSet 이라는 것을 제대로 인식하지 못할 것입니다. 해당 부분을 인식해주기 위해서는 EntitiyFramework Core 에 대한 참조가 필요합니다.
간단하게 Microsoft.EntityframeworkCore 패키지 최신 버전을 설치합니다. (주로 사용하는 버전이 있다면 그것으로 써도 괜찮습니다.)
VisualStudio 에서 시키는대로 설치를 완료하고 나면 맨 윗줄에 내용이 추가가 될 것입니다.
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TestBlog
{
public class BlogContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
}
public class Blog
{
public int BlogId { get; set; }
public string Name { get; set; }
}
}
그러면 이제 손으로 직접 커맨드를 실행시켜서 데이터베이스에 현재 내용을 넣어보도록 합시다.
위의 DbSet 은 하나의 테이블에 대응되고, 아래의 class는 테이블의 컬럼에 해당됩니다. 물론 자릿수, 키, 제약 등의 자세한 설정들도 처리가 가능하지만 여기에서는 생략하겠습니다.
VisualStudio 에서 "패키지 관리자 콘솔"을 찾아서 실행합니다.
상단 메뉴 => 보기 => 다른 창 => 패키지 관리자 콘솔 로 실행할 수 있습니다.
그리고 현재 하나 밖에 없는 프로젝트인 TestBlog 를 시작프로젝트로 지정합니다. (기본적으로 지정되어 있습니다.)
패키지 관리자 콘솔에서 다음 두 패키지를 설치합니다. 엔티티프레임워크의 자동생성을 위한 패키지입니다.
(nuget 관리자를 이용한 ui 설치 또는 커맨드 입력)
Microsoft.EntityFrameworkCore.Design
Microsoft.EntityFrameworkCore.Tools
Install-Package Microsoft.EntityFrameworkCore.Design
Install-Package Microsoft.EntityFrameworkCore.Tools
패키지 설치가 끝나면 어떤 Database에 접근해서 테이블을 생성해야할지 지정이 필요합니다.
DB 설정을 넣어주기 위해서 Program.cs 파일을 변경합니다.
기본적인 서비스 실행(윈도우서비스, ASP.NET CORE 등) 을 위해서 필요한 내용들입니다.
// Program.cs
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
namespace TestBlog
{
public class Program
{
public static void Main(string[] args)
{
Console.WriteLine("Hello, World!");
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args);
}
}
파일을 변경하고 나면 또 실행이 제대로 안되기 때문에 필요한 패키지들을 설치해줍니다. 각자 사용하는 데이터베이스가 있을 수 있으나 C#과 관련되어있기 때문에 SqlServer를 기본 패키지로 사용하였습니다. 사용하는 데이터베이스에 맞는 패키지를 찾아서 설치해주시면 됩니다.
Install-Package Microsoft.Extensions.Hosting
Install-Package Microsoft.EntityFrameworkCore.SqlServer
//Install-Package Microsoft.EntityFrameworkCore.Sqlite
설치가 완료되면 위 Program.cs 파일에서 보도록 정의한 설정파일인 appsettings.json 을 생성하고 ConnectionStrings:TestBlogConnStr 에 맞는 구조대로 json 데이터를 설정해줍니다.
기본적인 데이터베이스에 연결하기 위한 커넥션 정보 역시 어떤 데이터베이스를 사용하느냐에 따라 조금씩 달라집니다. 이것 역시 SqlServer 기준으로 작성되었습니다.
//appsettings.json
{
"ConnectionStrings": {
"TestBlogConnStr": "Data Source=데이터베이스IP;Initial Catalog=데이터베이스이름;Persist Security Info=True;Encrypt=False;User ID=사용자명;Password=패스워드;MultipleActiveResultSets=True",
}
}
마지막으로 Blog.cs 에서 appsettings.json 에 있는 커넥션 정보를 보도록 선언을 해줍니다.(OnConfiguring 함수 참조)
또한 생성자도 DbcontextOptions 를 가지도록 선언이 되어야합니다. (이게 없으면 커맨드로 데이터베이스를 생성하는 과정이 제대로 진행되지 않습니다.)
OnConfiguring 함수는 .NET CORE가 채용하고 있는 DI를 사용하지 않는 경우에 커넥션 정보를 획득할 수 있는 용도로 사용됩니다. 원칙적으로 콘솔이나 WinForm 등에서 사용되고, ASP.NET CORE 등의 경우에는 DI를 이용해서 Database에 접근합니다. 상세한 이용방식은 나중에 다시 글을 적어보겠습니다.
//Blog.cs
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
namespace TestBlog
{
public class BlogContext : DbContext
{
public BlogContext() { }
public BlogContext(DbContextOptions<BlogContext> options)
: base(options)
{
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
var builder = new ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile("appsettings.json");
var config = builder.Build();
var connectionString = config.GetConnectionString("TestBlogConnStr");
optionsBuilder.UseSqlServer(connectionString);
}
}
public DbSet<Blog> Blogs { get; set; }
}
public class Blog
{
public int BlogId { get; set; }
public string Name { get; set; }
}
}
여기까지 하고 나면 아래의 커맨드를 실행합니다.
Add-Migration InitialCreate
그러면 새로이 Migrations 라는 폴더가 프로젝트 안에 생기게 됩니다.
그리고 그 하위에는 시간_InitialCreate.cs 라는 파일과 BlogContextModelSnapshot.cs 라는 2개의 파일이 생성됩니다.
이후에는 다음 커맨드를 실행합니다.
그러면 InitialCreate 과 Snapshot 에 의한 데이터 변경분 만큼이 적용이 됩니다.
최초의 적용은 당연히 아무것도 없는 것이므로 모든 모델 데이터가 적용이 될 것입니다.
Update-Database
해당 Migrations 폴더에는 데이터베이스의 변경분이 모두 저장되어있고 그에 따라서 데이터의 변경사항을 같이 확인할 수 있습니다. 지금부터라도 매번 데이터베이스를 별도로 관리하는 어려움을 겪기보다는 이처럼 코드로 데이터베이스를 관리하는 것을 시도해보는 것은 어떨까요?
물론, 새로운 방식이므로 데이터를 실수로 날려버리지 않도록 개발하면서 미리미리 제대로 된 테스트를 진행하고 운영 서비스에 적용시에는 조심해서 적용을 해야 할 것입니다.
'C# > .Net Core' 카테고리의 다른 글
C#에서 예외필터(ExceptionFilter) 기능 사용해보기 (0) | 2024.05.05 |
---|---|
Asp.Net Core에서 GetService 와 GetRequiredService 의 차이 (0) | 2024.04.22 |
configurationBuilder() 에서 SetBasePath 찾을 수 없는 경우 (0) | 2024.04.09 |
댓글