2010-05-04 7 views
1

LinqToSql에서 사용하기에 정말 멋진 라이브러리를 작성했습니다. (언젠가 생각해 볼 시간이 있다면 언젠가는 오픈 소스로 만들 수도 있습니다 :) :)큰 Linq 트랜잭션으로 기하 감속을 피하는 방법은 무엇입니까?

어쨌든, 이것이 내 라이브러리와 관련이 있는지는 모르겠지만, 하나의 트랜잭션에서 많은 수의 변경된 오브젝트가 있고 DataContext.GetChangeSet()으로 호출하면 일이 시작됩니다 reaalllly slooowwwww. 코드에 침입했을 때, 나는 내 프로그램이 변경 세트의 객체들 사이에 끔찍한 많은 비교를하고있는 바퀴를 돌고 있다는 것을 발견했다. 이것이 사실이라는 것을 보장 할 수는 없지만, n 개체가 변경 집합에있는 경우 GetChangeSet()에 대한 호출로 인해 모든 개체가 동등성을위한 모든 다른 개체와 비교됩니다. 즉, 최대로 (n^2-n)/2 (으)로 전화하면 Equals() ...

물론 각 개체를 개별적으로 커밋 할 수는 있지만 트랜잭션 목적을 상실 할 수 있습니다. 그리고 제가 작성한 프로그램에서 10 만개의 개별 항목을 포함하는 일괄 작업을 수행 할 수있었습니다. 모두 함께 커밋해야합니다. 거기에 약 50 억 비교.

그래서 질문입니다 : (1) 상황의 정확한 평가입니까? 순수한 교과서 LinqToSql에서이 동작을 얻었습니까? 아니면 내 라이브러리에서이 작업을 수행하고 있습니까? 그리고 (2) 표준/합리적인 해결 방법이있어서 변경 세트의 모든 추가 객체로 프로그램의 기하학적 천천히 실행하지 않고 배치를 만들 수 있습니까?

답변

1

마지막으로 각 개별 항목이 하나의 큰 트랜잭션 내에서 독립적으로 저장되도록 배치를 다시 작성하기로 결정했습니다. 대신 즉, :

var b = new Batch { ... }; 
while (addNewItems) { 
    ... 
    var i = new BatchItem { ... }; 
    b.BatchItems.Add(i); 
} 
b.Insert(); // that's a function in my library that calls SubmitChanges() 

.. 당신은 같은 것을 할 필요가 : 첫 번째 코드 블록을 사용하는 것이 단지 깨끗하고 자연스러운 이유

context.BeginTransaction(); // another one of my library functions 
try { 
    var b = new Batch { ... }; 
    b.Insert(); // save the batch record immediately 
    while (addNewItems) { 
    ... 
    var i = new BatchItem { ... }; 
    b.BatchItems.Add(i); 
    i.Insert(); // send the SQL on each iteration 
    } 
    context.CommitTransaction(); // and only commit the transaction when everything is done. 
} catch { 
    context.RollbackTransaction(); 
    throw; 
} 

당신이 볼 수있는, 그리고 그건 나는 두 번째 구조를 사용하도록 강요 받았다. ...

관련 문제