[Entity Framework 6] 하나의 DB에 여러 컨텍스트(Multiple DbContext) 사용할 때 마이그레이션 관리하기
이전 포스팅에서는 하나의 DB에 여러 컨텍스트를 사용하기 위해 각각 마이그레이션을 생성해서 관리하는 방법을 사용했습니다.
이 방법은 여러 개의 마이그레이션을 관리해야 해서 불편함이 많습니다.
그래서 전체를 관리하는 컨텍스트를 만들고 마이그레이션과 조인이 필요할 때는 이 '전체 컨텍스트'를 따로 만들어 사용하는 것이 좋습니다.
0. 방법
이 방법의 단점은 전체용 컨텍스트를 따로 관리해야 한다는 것인데.....
관리와 성능의 이점을 생각하면 이 정도는 단점이라고 할수 없죠 ㅎㅎㅎㅎ
결국 마이그레이션만 따로 관리할 뿐 컨택스트를 하나만 쓰는 것과 다름없는 구조가 됩니다.
기본 세팅
이전 포스팅에서
(참고 : [Entity Framework 6] 하나의 DB에 여러 컨텍스트(Multiple DbContext) 사용하기 )
0. 프로젝트 생성 및 기본 세팅
1. 모델 생성
2. 컨텍스트(Context) 만들기
까지 따라 합니다.
1. 전체 컨텍스트 만들기
'ModelsDB'폴더에 'AllContext' 클래스를 생성합니다.
이 컨텍스트에는 관리할 모든 테이블의 'DbSet'을 넣어줍니다.
using EfMultipleContext2.Global;
using Microsoft.EntityFrameworkCore;
namespace ModelsDB;
public class AllContext : DbContext
{
#pragma warning disable CS8618
public virtual DbSet<StudentModel> Students { get; set; }
public virtual DbSet<TeacherModel> Teachers { get; set; }
#pragma warning restore CS8618
protected override void OnConfiguring(DbContextOptionsBuilder options)
{
options.UseSqlite(GlobalStatic.DBString);
}
}
2. 마이그레이션(Migration)
마이그레이션 생성은 'AllContext'만 하면 됩니다.
Add-Migration InitialCreate -Context ModelsDB.AllContext -OutputDir Migrations\AllMigrations
이제 아래 코드를 넣어두면 전체 마이그레이션이 됩니다.
(직접 EF명령어를 날려 마이그레이션 해도 됩니다.)
//전체 첫 마이그레이션 생성
//Add-Migration InitialCreate -Context ModelsDB.AllContext -OutputDir Migrations\AllMigrations
using (AllContext dbAll = new AllContext())
{
dbAll.Database.Migrate();
}
3. 테스트
테스트용으로 'Students'와 'Teachers'를 조인해 봅시다.
using (AllContext dbAll = new AllContext())
{
var all
= (from s in dbAll.Students
join t in dbAll.Teachers
on s.ID equals t.ID
select new { t, s })
.ToList();
Console.WriteLine(all);
}
조인도 잘되네요.
4. 다중 컨택스트 조인(join)
EF에서는 한 쿼리문에서 여러 컨택스트를 사용하는 걸 허용하지 않습니다.
그러므로 한쪽 컨택스트의 쿼리결과를 미리 받아야 합니다.
4-1. 오류 재연
아래 코드를 넣고 돌려봅시다.
using (StudentContext db_1 = new StudentContext())
{
using (TeacherContext db_2 = new TeacherContext())
{
var all
= (from s in db_1.Students
join t in db_2.Teachers
on s.ID equals t.ID
select new { t, s })
.ToList();
Console.WriteLine(all);
}
}
다음과 같은 에러가 납니다.
System.InvalidOperationException: 'Cannot use multiple context instances within a single query execution. Ensure the query uses a single context instance.'
단일 쿼리 실행 내에서 여러 컨텍스트 인스턴스를 사용할 수 없습니다. 쿼리가 단일 컨텍스트 인스턴스를 사용하는지 확인하십시오.
4-2. 해결 방법
방법이야 미리 리스트를 받아오는 방법뿐이 없습니다.
아래 코드는 '.ToList()'를 통해서 데이터를 미리 받아오고 있습니다.
using (StudentContext db_1 = new StudentContext())
{
using (TeacherContext db_2 = new TeacherContext())
{
List<StudentModel> listStu
= db_1.Students.ToList();
var all
= (from s in listStu
join t in db_2.Teachers
on s.ID equals t.ID
select new { t, s })
.ToList();
Console.WriteLine(all);
}
}
일반적으로 컨텍스트 하나로 조인하는 게 두 개로 조인하는 것보다 빠른데.....
상황에 따라서는 아닐 수도 있습니다.
(이 프로젝트도 컨텍스트 두 개 쓰는게 조금 더 빠릅니다 ㅎㅎㅎ)
마무리
테스트 프로젝트 : github - dang-gun/EntityFrameworkSample/MultipleContext2/
참고 : stackoverflow - An error occurred while accessing the Microsoft.Extensions.Hosting services when do first migrations - Shervin Ivari님 답변
이전 포스팅에 붙이기에는 주제가 안 맞고
따로 포스팅하자니 내용이 이전 포스팅과 겹치고....