문제

LINQ2SQL을 사용하여 CSV 파일의 내용을 데이터베이스 테이블에 삽입하려고합니다.

거래를 롤백 할 수 있기를 원합니다. 어느 인서트의 실패는 실패하지만이 코드로 시도하면 다음 오류가 발생합니다. db.transaction.commit ()

System.InvalidOperationException은 처리되지 않았습니다.이 SQLTransaction이 완료되었습니다. 더 이상 사용할 수 없습니다.

내가 뭘 잘못하고 있는지 아는 사람이 있습니까?

using (DataContext db = new DataContext())
{
    db.Connection.Open();
    db.Transaction = db.Connection.BeginTransaction();

    try
    {
        foreach (string entry in entries)
        {
            XXX xxx = new XXX()
            {
                P1 = "something",
                P2 = "something"
            };

            db.XXXX.InsertOnSubmit(xxx);
            db.SubmitChanges();
        }
    }
    catch (Exception)
    {
        db.Transaction.Rollback();
    }
    finally
    {
        db.Connection.Close();
    }

    db.Transaction.Commit();
}
도움이 되었습니까?

해결책

글쎄, 주문이 잘못되었습니다 - 당신은 db.Transaction.Commit() 전체 큰 블록 후에는 예외가 발생하고 이미 호출되는 경우에도 호출됩니다. db.Transaction.Rollback();

코드 변경 :

using (DataContext db = new DataContext())
{
    db.Connection.Open();
    db.Transaction = db.Connection.BeginTransaction();

    try
    {
        foreach (string entry in entries)
        {
            ....
            db.XXXX.InsertOnSubmit(xxx);
            db.SubmitChanges();
        }

        db.Transaction.Commit(); <== CALL HERE !!
    }
    catch (Exception)
    {
        db.Transaction.Rollback();
    }
    finally
    {
        db.Connection.Close();
    }
}

이 경우, 당신의 커밋은 foreach 이후에 호출되지만 아니다 예외가 발생하고 롤백을하는 경우 부름을 받으십시오.

마크

다른 팁

롤백을 한 후 커밋을하기 때문입니까?

시도 블록 내부에 커밋을 마지막으로 배치해야하므로 롤백 또는 커밋이 호출됩니다. 둘 다 ...

업데이트 : Peter가 그의 대답에서 언급 한 바와 같이, 나는 사용 블록이 연결을 처리 (따라서 닫히기)와 같은 닫기 또는 롤백 진술이 필요하지 않을 것으로 기대하고 있으며, 이는 커지지 않은 트랜잭션은 자동으로 롤백해야합니다.

"DataContext 사용"이 현재 트랜잭션과 연결이 닫히도록 보장한다는 사실에 근거하여 다음 블록이 충분하다고 가정합니다.

01.    using (DataContext db = new DataContext())
02.    {    
03.        db.Connection.Open();    
04.        db.Transaction = db.Connection.BeginTransaction();    
05.
06.        foreach (string entry in entries)        
07.        {                
08.            XXX xxx = new XXX()                
09.            {                        
10.                P1 = "something",                        
11.                P2 = "something"                
12.            };                
13.            db.XXXX.InsertOnSubmit(xxx);                
14.        }    
15.        db.SubmitChanges();        
16.
17.        db.Transaction.Commit();
18.    }

05 라인과 16 행 사이에 예외가 발생하면 트랜잭션과 코네티온이 18 행에서 완료 되 자마자 거래가 커밋으로 표시되지 않아 다시 롤백됩니다.

참고 : 여기서는 의도적이든 아니든 확실하지 않은 행동에 차이가 있습니다. 트랜잭션을 롤백하는 것 외에도 캐치 블록은 예외를 제외하고 오류가 발생했다는 사실을 숨 깁니다.

업데이트: 또한 내부 루프에서 호출을 꺼내는 것도 옮길 것입니다. 먼저 인서트를 수행 한 다음 모든 변경 사항에 대해 제출을 한 번 변경할 수 있어야합니다.

"Peter Lillevold"의 답변에 게시 된 코드와 관련하여 : 15 행 예를 들어 오류가 발생하면 DB.SubMitchanges ()에서 오류가 발생하면 데이터베이스 연결이 닫히지 않습니다. 따라서 올바른 솔루션은 다음과 같습니다.

enter code here
      using (DataContext db = new DataContext())
        {
            // The dispose method of DbConnection will close any open connection
            // and will rollback any uncommitted transactions
            using (DbConnection dbConnection = db.Connection)
            {
                dbConnection.Open();
                db.Transaction = dbConnection.BeginTransaction();
                foreach (string entry in entries)
                {
                    XXX xxx = new XXX()
                    {
                        P1 = "something",
                        P2 = "something"
                    };
                    db.XXXX.InsertOnSubmit(xxx);
                }
                db.SubmitChanges();
                db.Transaction.Commit();
            }
        } 

추신 : 추가 설명은 참조하십시오 http://msdn.microsoft.com/en-us/library/bb292288.aspx, "개방형 연결을 제공하면 데이터 컨텍스트가 닫히지 않습니다."라고 말합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top