2013-04-11 2 views
2

50 만 개가 넘는 레코드가 포함 된 테이블이 있습니다. 각 레코드에는 약 60 개의 필드가 있지만 그 중 세 필드 만 변경합니다.Entity Framework 4 SaveChanges의 메모리 부족

계산 및 조회를 기반으로 각 항목을 약간 수정합니다.

확실히 각 엔티티를 차례로 업데이트 할 수 없으며 그 다음으로는 SaveChanges으로 업데이트하는 데 너무 오래 걸릴 수 있습니다.

전체 프로세스가 끝나면 Context에서 SaveChanges이라고 부릅니다. 나는 내가 DataRepository 패턴을 사용하고 SaveChanges

를 적용 할 때

는 메모리 부족 오류를 일으키는 원인이된다.

//Update code 
DataRepository<ExportOrderSKUData> repoExportOrders = new DataRepository<ExportOrderSKUData>(); 
foreach (ExportOrderSKUData grpDCItem in repoExportOrders.all()) 
{ 
    ..make changes to enity.. 
} 
repoExportOrders.SaveChanges(); 



//Data repository snip 
public DataRepository() 
{ 
    _context = new tomEntities(); 
    _objectSet = _context.CreateObjectSet<T>(); 
} 
public List<T> All() 
{ 
    return _objectSet.ToList<T>(); 
} 
public void SaveChanges() 
{ 
    _context.SaveChanges(); 
} 

이 인스턴스에서 무엇을 찾고 있습니까?

+0

당신은 "분명히 각 엔티티를 차례로 업데이트 할 수 없으며 SaveChanges를 업데이트 할 수 없다"고 말했습니다. 임의의 레코드 수 (아마도 1024 또는 4096)에 대해 SaveChanges()를 호출 할 수 있습니까? –

+0

다음 게시물을 보았습니까 [http://stackoverflow.com/questions/5940225/fastest-way-of-inserting-in-entity-framework/5942176#5942176](http://stackoverflow.com/). 질문/5940225/가장 빠른 방법으로 엔터티 프레임 워크에 삽입/5942176 # 5942176)? –

+0

@David 그래, 그 시도, 그리고 확인을 작동하는 것,하지만이 최고의 * 기술 * 솔루션을 모르겠어요. 무슨 뜻인지 알 겠어? – griegs

답변

3

한 트랜잭션 내에서 EF를 통해 50 만 레코드로 변경하면 은 사용하지 않을 것으로 가정합니다.. 작은 배치로하는 것이 더 나은 기술적 솔루션입니다. 일부 저장 프로 시저를 통해 데이터베이스 측에서 작업하는 것이 더 나은 솔루션이 될 수 있습니다.

나는 약간 (저장소 API의 자신에 번역) 코드를 수정하여 시작할 것 :

using (var readContext = new YourContext()) { 
    var set = readContext.CreateObjectSet<ExportOrderSKUData>(); 

    foreach (var item in set.ToList()) { 
     readContext.Detach(item); 
     using (var updateContext = new YourContext()) { 
      updateContext.Attach(item); 
      // make your changes 
      updateContext.SaveChanges(); 
     } 
    } 
} 

이 코드는 항목을 저장하기위한 별도의 컨텍스트를 사용 = 각각의 고유 한 트랜잭션에 저장합니다. 저것을 두려워하지 말라. SaveChanges 한 통화 내에서 더 많은 레코드를 저장하려고해도 EF는 업데이트 된 모든 레코드에 대해 데이터베이스에 대해 별도의 왕복을 사용합니다. 단 하나의 차이점은 동일한 트랜잭션에서 여러 개의 업데이트를 원할 경우 (단, 단일 트랜잭션에서 50 만 건의 업데이트로 인해 문제가 발생할 수 있음).

또 다른 옵션이 될 수있다 : 당신이 이전에 foreach 일에로드 된 모든 개체를 할 필요가 없기 때문에

using (var readContext = new YourContext()) { 
    var set = readContext.CreateObjectSet<ExportOrderSKUData>(); 
    set.MergeOption = MergeOption.NoTracking; 

    foreach (var item in set) { 
     using (var updateContext = new YourContext()) { 
      updateContext.Attach(item); 
      // make your changes 
      updateContext.SaveChanges(); 
     } 
    } 
} 

이 이론에 더 적은 메모리를 소모 할 수 있습니다. 첫 번째 예제에서는 Detach (열거 중에 컬렉션 수정)을 호출 할 때 예외를 피하기 위해 열거 전에 (모든 호출을 ToList) 호출해야합니다.하지만 실제로 발생하는지는 확실하지 않습니다.

일부 배치를 사용하기 위해 이러한 예제를 수정하는 것이 쉬워야합니다.

+0

그들이 작동하지 않더라도 나는 이것들을 좋아한다. 나는 여전히 메모리 부족 오류가 발생합니다. 그러나 나는이 프로젝트에서해야 할 수도있는 다른 것들에 대한이 대답의 가치를 알 수있다. 감사합니다 – griegs

+1

메모리 프로파일 러를 사용하여 정확하게 문제의 원인을 찾아야합니다. 이 예제들 중 어느 것도 OOM 예외에 도움이되지 않는다면 더 큰 숨겨진 문제가있을 수 있습니다. –

+0

동의 함. 단순히 내 PC의 메모리가 부족하고 서버에서 문제가되지 않을 수도 있지만 지금은 그렇지 않은지 확인할 수 없습니다. 여기에 접근 할 수있는 이상한 비트. – griegs