EFCore 작동 질문...

안녕하세요
EFCore 이용한 개발중 의문점이생겼는데 속시원하게 해답을 못찾아서 질문드립니다…

public class DBDelegater
{
	private readonly ControleServerBase.DB.DbContextFactory<ControlContext> _contextFactory;
	ControleServerBase.DB.Context.ControlContext Context { get; set; }
	string[] blank = { "" };

	public DBDelegater()
	{
		_contextFactory = new();
		Context = _contextFactory.CreateDbContext(blank);
	}

	public async Task<DBModels.MobileSet> GetPosition(StatusData dtoContent)
	{
		~~~
		await Context.Positions.AddAsync(mobileSet.daoPosition);
		await Context.SaveChangesAsync();

		mobileSet.daoVacuum.positionId = mobileSet.daoPosition.id;

		await Context.Vacuums.AddAsync(mobileSet.daoVacuum);
		await Context.SaveChangesAsync();
		~~~
	}

	public async Task<DBModels.MobileSet> GetPosition2(StatusData dtoContent)
	{
		~~~
		await Context.Positions2.AddAsync(mobileSet.daoPosition);
		await Context.SaveChangesAsync();

		mobileSet.daoVacuum.positionId = mobileSet.daoPosition.id;

		await Context.Vacuums2.AddAsync(mobileSet.daoVacuum);
		await Context.SaveChangesAsync();
		~~~

	}
}

위와같이 DBDelegater라는놈 안에서 모든 DB작업을 진행하게 하고
다 비동기식으로 작업이 돌아가고있는상태입니다

질문은 아래와같습니다

  1. GetPosition 함수의 내용처럼 Positions 테이블에 데이터를 넣고 autoincrement 로 자동생성된 id를 Vacuums 데이터에 입력후 테이블에 집어넣는 로직이 있는데
    이경우 SaveChanges를 두번진행하게되는데 이를 간소화는 방법이 있을까요???

  2. Context를 하나 생성한뒤 이를 돌려쓰고있는데 만약 비동기로 여러개 함수가 돌아가고 있는상태에서 하나가 AddAsync로 데이터를 입력해두고 SaveChages로 테이블에 반영되는 사이에
    다른 함수에서 Context.ChangeTracker.Clear(); 작업을해서 트래커가 초기화된경우가 발생할수있나요??
    일단 jmeter 이용해서 일부로 발생시켜보려고했을땐 해당 에러가 발생은 안되었는데 속시원하게 이해가 되지않아서 질문드립니다

감사합니다…

1개의 좋아요
  1. 두 EF 테이블 개체가 FK로 인스턴스 참조가 되어있다면 Add 할 때 하나의 인스턴스와 관계된 인스턴스(목록)이 같이 저장됩니다. 이 때 키는 자동으로 입력됩니다.

  2. 컨텍스트를 다른 스레드와 공유해서 사용하면 안됩니다. 추측 하시는 것 처럼 트레킹에 문제가 생깁니다.

4개의 좋아요

감사합니다!!!

1개의 좋아요
  1. 두 엔티티 간 FK관계가 맺어져 있지 않다면 위의 소스코드처럼 2번을 해야하는게 맞습니다.
    다만 저렇게 처리해야하는 경우에는 보통 명시적으로 트랜젝션을 생성(BeginTransasction)하여
    처리 후 성공결과에 따라 Commit / Rollback을 해주는 것이 일반적입니다.

  2. 비동기로 여러 개의 함수가 동시에 돌아야 한다면 각 함수(스레드 단위)별로 DbContext를 따로 생성하도록 하여 처리하는게 좋습니다. 다만 위의 소스코드만을 대상으로 테스트를 하셨다면 각 비동기 메소드 마다 await 처리가 되어있으므로 각 비동기 메소드 간에 동시에 DbContext를 참조할 일은 없어 보이긴 합니다.

4개의 좋아요

혹시 DbContext를 재사용하시는 이유가 있으신가요?
일반적으로 DbContext는 논리적으로 가벼운 객체로 매 오퍼레이션 시 독립적으로 생성해서 사용해도 문제가 없는 것으로 알고 있습니다.

그리고 매 단위 실행마다 await 하지 않고 Task 안에서 단위 실행을 동기 처리하는게 어떨까 싶네요.

public async Task<DBModels.MobileSet> GetPosition(StatusData dtoContent)
{
     return await Task.Run(() =>
     {
         using(var context = _contextFactory.Create()) // returns a DataContext.
         {
             // do stuff.
         }
     });
}
4개의 좋아요