programing

엔티티 프레임워크6 트랜잭션롤백

testmans 2023. 4. 15. 08:30
반응형

엔티티 프레임워크6 트랜잭션롤백

EF6에서는 다음과 같은 새로운 트랜잭션을 사용할 수 있습니다.

using (var context = new PostEntityContainer())
        {
            using (var dbcxtransaction = context.Database.BeginTransaction())
            {
                try
                {
                    PostInformation NewPost = new PostInformation()
                    {
                        PostId = 101,
                        Content = "This is my first Post related to Entity Model",
                        Title = "Transaction in EF 6 beta"
                    };
                    context.Post_Details.Add(NewPost);
                    context.SaveChanges();
                    PostAdditionalInformation PostInformation = new PostAdditionalInformation()
                    {
                        PostId = (101),
                        PostName = "Working With Transaction in Entity Model 6 Beta Version"
                    };

                    context.PostAddtional_Details.Add(PostInformation);
                    context.SaveChanges();

                    dbcxtransaction.Commit();
                }
                catch
                {
                    dbcxtransaction.Rollback();
                }
            }
        }

일이 잘못될 때 롤백이 실제로 필요한가?Commit description에 "기본 스토어 트랜잭션을 커밋합니다."라고 쓰여있기 때문에 궁금합니다.

반면 롤백 설명에는 "기본 스토어 트랜잭션을 롤백합니다."라고 되어 있습니다.

Commit가 호출되지 않으면 이전에 실행한 명령어가 저장되지 않는 것처럼 보이기 때문에 궁금증이 생깁니다(논리적으로 보입니다).그러나 이 경우 롤백 함수를 호출해야 하는 이유는 무엇입니까?EF5에서는 롤백 기능(완료만)이 없는 Transaction Scope를 사용했습니다.이 기능은 논리적으로 보입니다.MS DTC의 이유로 더 이상 Transaction Scope를 사용할 수 없지만 위의 예와 같은 트라이 캐치는 사용할 수 없습니다(예: Commit만 필요합니다).

Rollback에 의해, 「」를 에,using★★★★★★ 。

DbContextTransaction.Dispose는 메서드의 됩니다.using또한 트랜잭션이 성공적으로 커밋되지 않은 경우(호출되지 않거나 예외가 발생한 경우) 트랜잭션이 자동으로 롤백됩니다.입니다.SqlInternalTransaction.Dispose메서드)DbContextTransaction.DisposeSQL Server를 사용합니다.

private void Dispose(bool disposing)
{
    // ...
    if (disposing && this._innerConnection != null)
    {
        this._disposing = true;
        this.Rollback();
    }
}

」, 「 」의 유무를 확인합니다._innerConnection늘이 않은 을 롤백합니다(커밋된 null로 롤백합니다)._innerConnection무효가 됩니다). 보자Commit하다

internal void Commit() 
{
    // Ignore many details here...

    this._innerConnection.ExecuteTransaction(...);

    if (!this.IsZombied && !this._innerConnection.IsYukonOrNewer)
    {
        // Zombie() method will set _innerConnection to null
        this.Zombie();
    }
    else
    {
        this.ZombieParent();
    }

    // Ignore many details here...
}

internal void Zombie()
{
    this.ZombieParent();

    SqlInternalConnection innerConnection = this._innerConnection;

    // Set the _innerConnection to null
    this._innerConnection = null;

    if (innerConnection != null)
    {
        innerConnection.DisconnectTransaction(this);
    }
}

SQL Server를 EF와 함께 항상 사용하는 한 롤백 메서드를 호출하기 위해 캐치를 명시적으로 사용할 필요는 없습니다.사용 중인 블록이 모든 예외에서 자동으로 롤백되도록 허용하면 항상 작동합니다.

그러나 엔티티 프레임워크의 관점에서 생각해 보면 모든 예에서 명시적 호출을 사용하여 트랜잭션을 롤백하는 이유를 알 수 있습니다.EF의 경우 데이터베이스 공급자는 임의적이며 플러그가 가능하며 공급자는 MySQL 또는 EF 공급자가 구현된 다른 데이터베이스로 대체될 수 있습니다.따라서 EF의 관점에서 볼 때, EF는 데이터베이스 공급자의 구현에 대해 알지 못하기 때문에 공급자가 폐기된 트랜잭션을 자동으로 롤백할 것이라는 보장은 없습니다.

따라서 EF 문서에서는 나중에 프로바이더를 폐기 시 자동 롤백되지 않는 구현으로 변경할 경우에 대비하여 명시적으로 롤백을 권장합니다.

적절하고 적절하게 작성된 프로바이더는 폐기 시 트랜잭션을 자동으로 롤백하기 때문에 트라이캐치 롤백을 사용하여 사용 블록 내의 모든 것을 랩하는 추가 작업은 오버킬이라고 생각합니다.

  1. 트랜잭션을 인스턴스화하기 위해 '사용' 블록을 작성했으므로 폐기 시 자동으로 롤백되므로 롤백 기능을 명시적으로 언급할 필요는 없습니다.
  2. 단, 사용 중인 블록을 사용하지 않고 인스턴스화할 경우 예외 발생 시(정확히 캐치 블록 내) 트랜잭션 롤백이 필수적이며, 보다 견고한 코드를 null로 체크하는 경우에도 마찬가지입니다.BeginTransaction의 동작은 트랜잭션 범위와는 다릅니다(모든 작업이 성공적으로 완료된 경우 완전한 기능만 필요합니다).대신 SQL 트랜잭션 작업과 비슷합니다.

언급URL : https://stackoverflow.com/questions/22486489/entity-framework-6-transaction-rollback

반응형