개요
이 가이드에서 EF Core 제공자 애플리케이션에서 트랜잭션 을 사용하는 방법을 학습할 수 있습니다. 트랜잭션은 일련의 쓰기 작업을 래핑합니다. 트랜잭션의 작업 중 하나라도 실패하면 제공자가 트랜잭션의 모든 변경 사항을 롤백합니다. 이러한 동작은 데이터 일관성을 보장하는 데 도움을 줍니다.
EF Core Provider는 다음 트랜잭션 모드를 지원합니다.
암시적 트랜잭션: 제공자는
SaveChanges()및SaveChangesAsync()메서드에 대한 호출을 트랜잭션에 자동으로 래핑합니다. 이 동작을 구성하거나 비활성화하는 방법을 알아보려면 암시적 트랜잭션 구성 을 참조하세요.명시적 트랜잭션:
Database.BeginTransaction()메서드를 호출하여 수동으로 트랜잭션을 시작하고, 그러한 다음Commit()또는Rollback()를 호출하여 트랜잭션을 커밋하거나 롤백합니다.
샘플 데이터
이 가이드 의 예제에서는 sample_guides 데이터베이스 의 planets 컬렉션 사용합니다. 이 컬렉션 의 문서는 다음 Planet 클래스를 모델로 사용합니다.
public class Planet { public ObjectId _id { get; set; } public string name { get; set; } = null!; public int orderFromSun { get; set; } public bool hasRings { get; set; } }
이 컬렉션은 Atlas에서 제공하는 샘플 데이터 세트 에서 가져온 것입니다. EF Core 제공자 사용 시작 가이드를 참조하여 무료 MongoDB 클러스터를 생성하고 이 샘플 데이터를 로드하는 방법을 학습합니다.
요구 사항 및 제한 사항
트랜잭션을 사용하기 전에 다음 요구 사항 및 제한 사항을 유의하세요.
트랜잭션에는 복제본 세트 또는 샤딩된 클러스터 와 같은 다중 문서 트랜잭션을 지원하는 MongoDB Server 배포서버 필요합니다. 애플리케이션 독립형 배포서버 에서 트랜잭션 시작하려고 하면 제공자 가
NotSupportedException을 발생시킵니다. 이를 방지하려면 암시적 트랜잭션 구성에 설명된 대로AutoTransactionBehavior.Never를 설정하다 .EF Core 제공자는
System.Transactions.TransactionScope에 의해 만들어진 것과 같은 .NET 애비언트 트랜잭션을 지원하지 않습니다. 애비언트 트랜잭션을 사용하려고 하면 제공자가 예외를 발생시킵니다. 대신 임플리시트 또는 명시적 트랜잭션을 사용하십시오.
임시적 트랜잭션
기본값으로 여러 루트 엔터티 가 영향을 받는 경우 EF Core Provider는 트랜잭션에서 SaveChanges() 및 SaveChangesAsync() 호출을 자동으로 래핑합니다. 루트 엔터티는 다른 문서 내에 저장되는 소유 유형 또는 내장된 유형과 달리 컬렉션 의 최상위 문서 입니다.
다음 예시에서는 단일 SaveChanges() 호출에서 두 개의 행성을 삽입합니다. 이 작업은 두 개 이상의 루트 개체에 영향을 주므로 제공자가 자동으로 트랜잭션으로 랩싹니다. 삽입 중 하나라도 실패하면 제공자가 두 개의 변경 사항을 모두 롤백합니다.
Synchronous 또는 Asynchronous 탭을 선택하여 해당 코드를 확인합니다.
dbContext.Planets.AddRange( new Planet { Name = "Mercury" }, new Planet { Name = "Venus" } ); // Both inserts succeed or both are rolled back dbContext.SaveChanges();
dbContext.Planets.AddRange( new Planet { Name = "Mercury" }, new Planet { Name = "Venus" } ); // Both inserts succeed or both are rolled back await dbContext.SaveChangesAsync();
암시적 트랜잭션 구성
DbContext 객체에 있는 Database.AutoTransactionBehavior 속성은 제공자가 암시적 트랜잭션을 사용하는 시기를 제어합니다. 이 속성은 AutoTransactionBehavior 열거형에서 값을 허용합니다. 이 열거형에는 다음 값이 포함되어 있습니다.
값 | 설명 |
|---|---|
| 제공자는 |
| 제공자는 단일 엔터티 작업에도 항상 트랜잭션을 사용합니다. |
| 제공자는 트랜잭션을 사용하지 않습니다. |
이 속성은 다음 예시에서 볼 수 있듯이 SaveChanges() 또는 SaveChangesAsync() 메서드를 호출하기 전 어떤 시점에든 설정할 수 있습니다. 해당 코드를 확인하려면 Synchronous 또는 Asynchronous 탭을 선택합니다.
dbContext.Database.AutoTransactionBehavior = AutoTransactionBehavior.Never; // This SaveChanges() call will not use a transaction dbContext.Planets.Add(new Planet { Name = "Mars" }); dbContext.SaveChanges();
dbContext.Database.AutoTransactionBehavior = AutoTransactionBehavior.Never; // This SaveChangesAsync() call will not use a transaction dbContext.Planets.Add(new Planet { Name = "Mars" }); await dbContext.SaveChangesAsync();
명시적 트랜잭션
명시적 트랜잭션을 사용하여 여러 SaveChanges() 호출 및 기타 작업을 단일 아토믹 작업 단위로 그룹할 수 있습니다. 명시적 트랜잭션을 시작하려면 Database.BeginTransaction() 또는 Database.BeginTransactionAsync() 메서드를 호출하세요. 작업을 수행한 후 Commit() 또는 CommitAsync() 를 호출하여 트랜잭션을 완료합니다.
다음 예시는 단일 트랜잭션에 여러 작업을 래핑하여 이 패턴을 보여줍니다. 작업이 예외를 발생시키면 제공자는 트랜잭션의 모든 변경 사항을 자동으로 롤백합니다. Synchronous 또는 Asynchronous 탭을 선택하여 해당 코드를 확인합니다.
using var transaction = dbContext.Database.BeginTransaction(); var planet = dbContext.Planets.First(p => p.Name == "Mercury"); planet.Name = "Mercury (Updated)"; dbContext.SaveChanges(); dbContext.Planets.Add(new Planet { Name = "Venus" }); dbContext.SaveChanges(); transaction.Commit();
await using var transaction = await dbContext.Database.BeginTransactionAsync(); var planet = await dbContext.Planets.FirstAsync(p => p.Name == "Mercury"); planet.Name = "Mercury (Updated)"; await dbContext.SaveChangesAsync(); dbContext.Planets.Add(new Planet { Name = "Venus" }); await dbContext.SaveChangesAsync(); await transaction.CommitAsync();
팁
수동 롤백
이 페이지의 예시에서는 using 선언을 사용하여 트랜잭션을 자동으로 롤백하고 트랜잭션 객체를 패기합니다. 트랜잭션을 수동으로 롤백하려면 catch 블록에서 Rollback() 또는 RollbackAsync() 메서드를 호출합니다.
명시적 트랜잭션 구성
TransactionOptions 객체 BeginTransaction() 또는 BeginTransactionAsync() 메서드에 전달하여 트랜잭션 에 대한 읽기 고려 (read concern), 쓰기 고려 (write concern), 읽기 설정 (read preference) 및 최대 커밋 시간을 구성할 수 있습니다.
TransactionOptions 클래스에는 다음과 같은 속성이 있습니다.
속성 | 유형 | 설명 |
|---|---|---|
|
| 트랜잭션의 첫 번째 명령에 대한 읽기 고려 (read concern). 기본값은 |
|
| 트랜잭션 내 읽기 작업에 대한 읽기 설정 (read preference)입니다. 트랜잭션은 프라이머리 에서 읽어야 합니다. 기본값 은 |
|
|
|
|
| 단일 |
다음 예시는 ReadConcern 이 Majority인 트랜잭션을 시작합니다. 해당 코드를 확인하려면 Synchronous 또는 Asynchronous 탭을 선택합니다.
var options = new TransactionOptions( readConcern: new Optional<ReadConcern>(ReadConcern.Majority) ); using var transaction = dbContext.Database.BeginTransaction(options); var planet = dbContext.Planets.First(p => p.Name == "Mercury"); planet.Name = "Mercury (Updated)"; dbContext.SaveChanges(); transaction.Commit();
var options = new TransactionOptions( readConcern: new Optional<ReadConcern>(ReadConcern.Majority) ); await using var transaction = await dbContext.Database.BeginTransactionAsync(options); var planet = await dbContext.Planets.FirstAsync(p => p.Name == "Mercury"); planet.Name = "Mercury (Updated)"; await dbContext.SaveChangesAsync(); await transaction.CommitAsync();
읽기 고려 (read concern), 쓰기 고려 (write concern) 및 읽기 설정 (read preference)에 대한 자세한 내용은 읽기 고려 (read concern), 쓰기 고려 (write concern) 및 읽기 설정 (read preference)에서 학습할 수 있습니다.
트랜잭션 제한
트랜잭션을 사용할 때는 다음과 같은 제한 사항 및 주의 사항이 적용됩니다.
배포서버가 자동 트랜잭션을 지원하지 않는 경우에만 비활성화합니다. 자동 트랜잭션을 비활성화하면 데이터 불일치가 발생할 수 있으며 낙관적 동시성을 사용할 수 없습니다.
MongoDB Server는 중청 트랜잭션을 지원하지 않습니다. 트랜잭션이 이미 활성화되어 있는 동안
BeginTransaction()또는BeginTransactionAsync()을 호출하면 제공자가InvalidOperationException를 오류로 발생시킵니다.MongoDB Server는 트랜잭션 저장점을 지원하지 않습니다. 전체 트랜잭션을 커밋하거나 롤백해야 합니다.
기본적으로 MongoDB Server는
transactionLifetimeLimitSeconds서버 매개변수에 의해 제어되는 데로 60 초 이상 실행되는 모든 트랜잭션을 중단합니다. 이 제한은 임시적 트랜잭션과 명시적 트랜잭션 모두에 적용됩니다. 트랜잭션이 이 시간 제한을 초과하면 MongoDB Server는 트랜잭션을 중단하고 제공자는 오류를 발생시킵니다. 트랜잭션 내에서 외부 API 호출과 같은 장기 실행 작업을 수행하지 마십시오.MongoDB Server에 네트워크 중단이 발생하거나 복제본 세트 투표를 수행해야 하는 경우
TransientTransactionError오류가 반환될 수 있습니다. 이러한 경우 EF Core Provider는 트랜잭션을 자동으로 다시 시도하지 않습니다. 일시적 트랜잭션 오류와 다시 시도 전략에 대해 자세히 알아보려면 트랜잭션 오류 처리를 참조하십시오.
추가 정보
이 가이드의 개념에 대해 자세히 알아보려면 다음 리소스를 참조하세요.
이 가이드에서 사용되는 메서드에 대해 자세히 학습하려면 다음 .NET API 문서를 참조하십시오.