프로젝트를 진행하다 보면 여러 가지 이유로 컨텍스트(Context)를 분리해서 관리할 필요가 있죠.
권장은 하나의 DB에 하나의 컨텍스트를 사용하는 것이지만
하나의 DB에 여러 컨텍스트를 사용하는 것도 가능합니다.
여러 컨텍스트를 조인하게 되면 성능이 확 떨어지고 조건에 따라서 마이그레이션 명령이 안 먹힐 수 있습니다.
그래서 하나의 컨텍스트를 사용하는 것을 권장하는 것입니다.
이 포스팅에서는 하나의 DB에 여러 컨텍스트를 사용하는 방법에 대해 알아봅시다.
이 포스팅에서는 'SQLite'를 사용할 예정입니다.
(다른 DBMS도 동일합니다.)
프로젝트를 생성하고 누겟(Nuget)에서 다음 종속성을 찾아 추가합니다.
- Microsoft.EntityFrameworkCore
- Microsoft.EntityFrameworkCore.Sqlite
- Microsoft.EntityFrameworkCore.Tools
'Global' 폴더를 만들고 'GlobalStatic.cs'를 추가합니다.
내용은 아래와 같습니다.
namespace EfMultipleContext.Global;
/// <summary>
/// 이 프로젝트에서 사용할 전역 변수
/// </summary>
public static class GlobalStatic
{
/// <summary>
/// DB 타입
/// </summary>
/// <remarks>저장전에 소문자로 변환해야 한다.</remarks>
public static string DBType = "sqlite";
/// <summary>
/// DB 컨낵션 스트링 저장
/// </summary>
public static string DBString = "Data Source=Test.db";
}
각각의 컨텍스트에 사용할 모델을 만듭니다.
'ModelsDB' 폴더를 만들어줍니다.
'StudentModel.cs'를 생성하고 아래와 같이 넣어줍니다.
using System.ComponentModel.DataAnnotations.Schema;
using System.ComponentModel.DataAnnotations;
namespace ModelsDB;
public class StudentModel
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ID { get; set; }
public string LastName { get; set; } = string.Empty;
public string FirstMidName { get; set; } = string.Empty;
public DateTime EnrollmentDate { get; set; }
}
'TeacherModel.cs'를 생성하고 아래와 같이 넣어줍니다.
using System.ComponentModel.DataAnnotations.Schema;
using System.ComponentModel.DataAnnotations;
namespace ModelsDB;
public class TeacherModel
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ID { get; set; }
public string LastName { get; set; } = string.Empty;
public string FirstMidName { get; set; } = string.Empty;
public DateTime HireDate { get; set; }
}
이제 위에서 만들 모델을 사용하는 각각의 DB컨텍스트(DbContext)를 만들어 줍니다.
'StudentContext.cs'를 생성하고 아래 코드를 넣어줍니다.
using EfMultipleContext.Global;
using Microsoft.EntityFrameworkCore;
namespace ModelsDB;
public class StudentContext : DbContext
{
#pragma warning disable CS8618
public virtual DbSet<StudentModel> Students { get; set; }
#pragma warning restore CS8618
protected override void OnConfiguring(DbContextOptionsBuilder options)
{
options.UseSqlite(GlobalStatic.DBString);
}
}
'TeacherContext.cs'를 생성하고 아래 코드를 넣어줍니다.
using EfMultipleContext.Global;
using Microsoft.EntityFrameworkCore;
namespace ModelsDB;
public class TeacherContext : DbContext
{
#pragma warning disable CS8618
public virtual DbSet<TeacherModel> Teachers { get; set; }
#pragma warning restore CS8618
protected override void OnConfiguring(DbContextOptionsBuilder options)
{
options.UseSqlite(GlobalStatic.DBString);
}
}
컨텍스트가 두 개이므로 마이그래이션도 각각 관리해야 합니다.
'패키지 관리자 콘솔(package manager console, PM)'에
마이그레이션 생성 명령어인 'Add-Migration'에 옵션을 설정하여
각각의 폴더를 지정한 후
마이그레이션이 생성될 수 있게 합니다.
아래 명령을 이용하여 학생 컨텍스트용 마이그레이션을 생성합니다.
Add-Migration InitialCreate -Context ModelsDB.StudentContext -OutputDir Migrations\StudentMigrations
아래 명령을 이용하여 선생 컨텍스트용 마이그레이션을 생성합니다.
Add-Migration InitialCreate -Context ModelsDB.TeacherContext -OutputDir Migrations\TeacherMigrations
두 마이그레이션이 생성되었으면 아래와 같은 구조가 됩니다.
이제 마이그레이션 내용을 DB에 적용하고 데이터를 넣어봅시다.
마이그레이션은 'EF Tool'을 이용해서 명령어로 업데이트할 수 있지만
여기서는 코드에서 진행합니다.
아래 코드를 이용해 마이그레이션을 적용할 수 있습니다.
(한번은 실행해야 함)
//학생 마이그레이션 적용
using (StudentContext db1 = new StudentContext())
{
db1.Database.Migrate();
}
//선생 마이그레이션 적용
using (TeacherContext db2 = new TeacherContext())
{
db2.Database.Migrate();
}
마이그레이션이 적용되었으면 아래와 같이 테이블이 각각 생성된 것을 확인할 수 있습니다.
이제 우리가 일상적으로 'EF'를 사용하는 것처럼 데이터를 넣어 봅시다.
//테스트 데이터 넣기
using (StudentContext db1 = new StudentContext())
{
db1.Students.Add(
new StudentModel()
{
LastName = "s1",
FirstMidName = "s2",
EnrollmentDate = DateTime.Now,
});
db1.SaveChanges();
}
using (TeacherContext db2 = new TeacherContext())
{
db2.Database.Migrate();
db2.Teachers.Add(
new TeacherModel()
{
LastName = "t1",
FirstMidName = "t2",
HireDate = DateTime.Now,
});
db2.SaveChanges();
}
실행 후 DB를 확인해 보면
데이터가 잘 들어갔음을 알 수 있습니다.
테스트 프로젝트 : github - dang-gun/EntityFrameworkSample/MultipleContext/
참고 : MS Learn - 여러 공급자를 사용하여 마이그레이션
EF가 업데이트되면서 예전에 쓰던 명령어가 사라지는 바람에.....
검색자료가 뒤죽박죽이라 겨우 찾았네요;;;
여기서 조심해야 할 것이 상황에 따라서 몇몇 마이그레이션 명령이 먹히지 않는 경우가 있습니다.
그래서 가급적 한 개의 DB에는 한 개의 마이그레이션만 사용하는 것이 좋은 것이죠.