Entity Framework Core를 이용한 SQL Server, MySQL, SQLite 연동

.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. 엔티티 클래스 정의

데이터베이스 테이블에 매핑될 엔티티 클래스를 정의합니다. 여기서는 BlogPost 두 개의 엔티티를 예시로 사용합니다.


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 등)에 저장하고, 리플렉션 등을 활용하여 동적으로 데이터베이스를 선택하는 방식으로 확장할 수 있습니다.

태그: Entity Framework Core EF Core SQL Server MySQL SQLite

6월 22일 20:36에 게시됨