28

Entity Framework에서 생성 된 컨텍스트 개체는 스레드로부터 안전하지 않습니다.Entity Framework 스레드 보안

각 스레드마다 하나씩 두 개의 별도 엔티티 컨텍스트를 사용하면 (각각 SaveChanges()) - 스레드로부터 안전할까요?

// this method is called from several threads concurrently 
public void IncrementProperty() 
{ 
    var context = new MyEntities(); 

    context.SomeObject.SomeIntProperty++; 
    context.SaveChanges(); 
} 

내가 엔티티 프레임 워크 컨텍스트 컨텍스트의 현재 값이 신선한 지 아닌지를 추적 '카운터'변수의 일종을 구현 생각합니다.

  1. 별도의 스레드에서 호출 된 위 코드를 사용하면 increment/savechanges를 잠글 필요가 있습니까?
  2. 그렇다면이 간단한 시나리오에서이를 수행하는 기본 방법은 무엇입니까?
+0

* "컨텍스트를 수신하여 저장소를 변경하는 데 필요한 방법을 호출, 아주 쉬운 방법으로 그렇게 할 수 Ninject에 대한 확장이 있습니다

http://elvanydev.com/EF-DbContextFactory/

Entity Framework는 스레드로부터 안전하지 않습니다. "* - 왜 그렇게 말합니까? – RPM1984

+0

MSDN을 참조하고 있습니다 : http://msdn.microsoft.com/en-us/library/system.data.objects.objectcontext.aspx "ObjectContext 클래스는 스레드로부터 안전하지 않습니다." – Harper

+0

네, 그건 당신이 의미하는 줄 알았던 것입니다. 그래서 OC에 싱글 톤을 사용하면 안됩니다. – RPM1984

답변

31

단일 Entity Framework 컨텍스트에서 작동하는 하나의 스레드는 스레드로부터 안전하지 않습니다.

각 스레드에 대한 별도의 컨텍스트 인스턴스는 스레드로부터 안전합니다. 실행의 각 스레드가 EF 컨텍스트의 자체 인스턴스가있는 한 당신은 괜찮을 것이다.

예제에서 모든 스레드에서 해당 코드를 동시에 호출 할 수 있으며 각 스레드는 자체 컨텍스트로 행복하게 작업 할 수 있습니다.

// this method is called from several threads concurrently 
public void IncrementProperty() 
{ 
    using (var context = new MyEntities()) 
    { 
     context.SomeObject.SomeIntProperty++; 
     context.SaveChanges(); 
    } 
} 
+0

감사합니다. 그렇다면 SubmitChanges()를 할 때 SomeIntProperty의 실제 값을 읽을 수 있습니까? 첫 번째 스레드가 값을 3으로 증가 시키면 두 번째 스레드가 잠재적으로 여전히 어딘가에 캐시 된 값 2를 갖게 될지, 아니면 그 위치에서 값을 검색 할 것인가? – Harper

+0

저는 여러분의 모범을 두 가지 중요한 측면에서 간과했습니다. 먼저 'SomeObject'를 검색하고 인스턴스화하는 코드가 없습니다. 따라서 표시된 코드는 작동하지 않습니다. 컨텍스트간에 캐시, 버퍼 또는 잠금을 공유하지 않습니다. 따라서 컨텍스트 인스턴스가있는 각 스레드는 두 개의 다른 시스템에서 실행중인 프로세스와 동일한 방식으로 생각할 수 있습니다. 따라서 데이터베이스 동시성 문제를 적절히 다뤄야합니다. –

+1

데이터베이스 동시 처리 문제를 해결하려면 낙관적 동시성 또는 데이터베이스 트랜잭션을 구현해야합니다. –

0

"SomeObject.SomeIntProperty"는 정적입니다. 이것은 엔티티가 스레드 세이프 인 것과 아무런 관련이 없습니다. 다중 쓰레드 환경에서 Static 변수에 쓰려면 쓰레드 안전을 보장하기 위해 항상 이중 체크 락으로 포장해야합니다.

0

당신은 이것 좀보세요, 대신 인스턴스 perse의 공장으로 당신의 DbContext를 주입 공장 접근 방식을 사용하여 다음과 같이

그러나, 나는 이것에 대한 '사용'블록을 구현 제안 : https://github.com/vany0114/EF.DbContextFactory

인스턴스 작성을 저장소에 하드 코딩하는 것을 피하십시오. 단지 kernel.AddDbContextFactory<YourContext>();은 또한에 의해 생성 된 객체 Func<YourContext>