프로그래밍/DB, SQL, EF

[Entity Framework 6] 하나의 DB에 여러 컨텍스트(Multiple DbContext) 사용할 때 마이그레이션 관리하기

당근천국 2022. 9. 29. 15:30

이전 포스팅에서는 하나의 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님 답변

 

이전 포스팅에 붙이기에는 주제가 안 맞고

따로 포스팅하자니 내용이 이전 포스팅과 겹치고....