.NET 7 환경에서 Entity Framework Core (EF Core)를 사용하여 SQL Server, MySQL, SQLite 데이터베이스를 연동하는 방법을 설명합니다. 먼저, .NET 7 콘솔 애플리케이션을 생성하고 필요한 NuGet 패키지를 설치합니다.
1. 프로젝트 설정 및 NuGet 패키지 설치
.NET CLI를 사용하여 프로젝트를 생성하고 EF Core 관련 패키지를 설치합니다. 사용하는 데이터베이스에 맞는 Provider 패키지를 추가해야 합니다.
dotnet new console -o EfCoreDemo
cd EfCoreDemo
dotnet add package Microsoft.EntityFrameworkCore.Design
dotnet add package Microsoft.EntityFrameworkCore.Tools
# 데이터베이스별 Provider 설치 (예시)
dotnet add package Microsoft.EntityFrameworkCore.Sqlite # SQLite
# dotnet add package Microsoft.EntityFrameworkCore.SqlServer # SQL Server
# dotnet add package Pomelo.EntityFrameworkCore.MySql # MySQL
2. 엔티티 클래스 정의
데이터베이스 테이블에 매핑될 엔티티 클래스를 정의합니다. 여기서는 Blog와 Post 두 개의 엔티티를 예시로 사용합니다.
public class Blog
{
public int BlogId { get; set; }
public string? Url { get; set; }
public int Rating { get; set; }
public List<Post> Posts { get; set; } = new List<Post>();
}
public class Post
{
public int PostId { get; set; }
public string? Title { get; set; }
public string? Content { get; set; }
public int BlogId { get; set; }
public Blog? Blog { get; set; }
}
3. DbContext 클래스 구현
DbContext를 상속받는 추상 클래스를 정의하고, 각 데이터베이스에 맞는 구체적인 DbContext 클래스를 구현합니다. OnConfiguring 메서드에서 데이터베이스 연결 정보를 설정합니다.
using Microsoft.EntityFrameworkCore;
// 추상 DbContext 클래스
public abstract class BloggingDbContextBase : DbContext
{
public DbSet<Blog> Blogs { get; set; } = null!;
public DbSet<Post> Posts { get; set; } = null!;
protected BloggingDbContextBase(DbContextOptions options) : base(options) { }
}
// SQL Server DbContext
public class SqlServerBloggingContext : BloggingDbContextBase
{
private readonly string _connectionString;
public SqlServerBloggingContext(string connectionString) : base(new DbContextOptions<SqlServerBloggingContext>())
{
_connectionString = connectionString;
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(_connectionString);
}
}
// MySQL DbContext
public class MySqlBloggingContext : BloggingDbContextBase
{
private readonly string _connectionString;
private readonly MySqlServerVersion _serverVersion;
public MySqlBloggingContext(string connectionString, MySqlServerVersion serverVersion)
: base(new DbContextOptions<MySqlBloggingContext>())
{
_connectionString = connectionString;
_serverVersion = serverVersion;
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseMySql(_connectionString, _serverVersion);
}
}
// SQLite DbContext
public class SqliteBloggingContext : BloggingDbContextBase
{
public string DbPath { get; }
public SqliteBloggingContext() : base(new DbContextOptions<SqliteBloggingContext>())
{
var folder = Environment.SpecialFolder.LocalApplicationData;
var path = Environment.GetFolderPath(folder);
DbPath = Path.Join(path, "blogging_efcore.db");
}
protected override void OnConfiguring(DbContextOptionsBuilder options)
=> options.UseSqlite($"Data Source={DbPath}");
}
4. 마이그레이션 (Code-First)
EF Core의 마이그레이션 기능을 사용하여 데이터베이스 스키마를 생성하거나 업데이트합니다. 여러 DbContext를 사용하는 경우, 각 마이그레이션에 대해 대상 DbContext와 출력 경로를 지정해야 합니다.
먼저, EF Core 도구를 전역으로 설치합니다.
dotnet tool install --global dotnet-ef
각 데이터베이스별 마이그레이션 파일을 생성하고 데이터베이스를 업데이트합니다.
# SQL Server 마이그레이션
dotnet ef migrations add InitialSqlServerCreate -c SqlServerBloggingContext -o Migrations/SqlServer
dotnet ef database update --context SqlServerBloggingContext
# MySQL 마이그레이션
dotnet ef migrations add InitialMySqlCreate -c MySqlBloggingContext -o Migrations/MySql
dotnet ef database update --context MySqlBloggingContext
# SQLite 마이그레이션
dotnet ef migrations add InitialSqliteCreate -c SqliteBloggingContext -o Migrations/Sqlite
dotnet ef database update --context SqliteBloggingContext
참고: MySQL의 경우, 데이터베이스가 미리 생성되어 있어야 할 수 있습니다.
5. CRUD 작업 예제
DbContext를 사용하여 데이터를 생성, 조회, 수정, 삭제하는 정적 메서드를 구현합니다.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
public static class BlogDataOperations
{
public static async Task CreateBlogsAsync(BloggingDbContextBase db)
{
Console.WriteLine("새로운 블로그 및 게시물 추가 중...");
for (int i = 0; i < 5; i++)
{
var blog = new Blog { Url = $"http://sampleblog{i}.com", Rating = i + 1 };
for (int j = 0; j < 3; j++)
{
blog.Posts.Add(new Post { Title = $"Post {j} for Blog {i}", Content = $"Content for Post {j}" });
}
db.Blogs.Add(blog);
await db.SaveChangesAsync();
Console.WriteLine($"Blog {i} added successfully.");
}
}
public static void DeleteAllBlogs(BloggingDbContextBase db)
{
Console.WriteLine("모든 블로그 삭제 중...");
var allBlogs = db.Blogs.ToList();
db.Blogs.RemoveRange(allBlogs);
db.SaveChanges();
Console.WriteLine("모든 블로그 삭제 완료.");
}
public static Blog? SelectFirstBlog(BloggingDbContextBase db)
{
Console.WriteLine("첫 번째 블로그 조회 중...");
return db.Blogs.Include(b => b.Posts).FirstOrDefault();
}
public static async Task UpdateBlogUrlAsync(BloggingDbContextBase db, int blogId, string newUrl)
{
Console.WriteLine($"Blog ID {blogId} 업데이트 중...");
var blogToUpdate = await db.Blogs.FindAsync(blogId);
if (blogToUpdate != null)
{
blogToUpdate.Url = newUrl;
await db.SaveChangesAsync();
Console.WriteLine($"Blog ID {blogId} URL이 '{newUrl}'(으)로 업데이트되었습니다.");
}
else
{
Console.WriteLine($"Blog ID {blogId}를 찾을 수 없습니다.");
}
}
}
6. DbContext 호출 및 사용
애플리케이션에서 원하는 데이터베이스의 DbContext 인스턴스를 생성하고, 구현된 CRUD 메서드를 호출합니다.
// SQLite 사용 예시
using var dbContext = new SqliteBloggingContext();
await BlogDataOperations.CreateBlogsAsync(dbContext);
var firstBlog = BlogDataOperations.SelectFirstBlog(dbContext);
if (firstBlog != null)
{
Console.WriteLine($"Found Blog: {firstBlog.Url}");
foreach (var post in firstBlog.Posts)
{
Console.WriteLine($"- Post: {post.Title}");
}
await BlogDataOperations.UpdateBlogUrlAsync(dbContext, firstBlog.BlogId, "https://updated.blog.com");
}
// BlogDataOperations.DeleteAllBlogs(dbContext);
// 다른 데이터베이스를 사용하려면 해당 DbContext 클래스의 인스턴스를 생성하고 연결 문자열을 설정합니다.
// 예:
// string sqlServerConnectionString = "Server=your_server;Database=BloggingDb;Trusted_Connection=True;";
// await using var sqlServerContext = new SqlServerBloggingContext(sqlServerConnectionString);
// await BlogDataOperations.CreateBlogsAsync(sqlServerContext);
연결 문자열은 구성 파일(appsettings.json 등)에 저장하고, 리플렉션 등을 활용하여 동적으로 데이터베이스를 선택하는 방식으로 확장할 수 있습니다.