Overview
このガイドでは、F Core プロバイダー アプリケーションでトランザクションを使用する方法を学習できます。トランザクションは一連の書込み (write) 操作をラップします。トランザクション内のいずれかの操作が失敗した場合、プロバイダーはトランザクション内のすべての変更をロールバックします。この動作は、データの一貫性を確保するのに役立ちます。
FS コア プロバイダーは、次のトランザクション モードをサポートしています。
暗黙的なトランザクション: プロバイダーはトランザクション内の メソッドと
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 が提供するサンプルデータセット から構成されています。無料のMongoDBクラスターを作成し、このサンプルデータをロードする方法については、 クイック スタートガイドを参照してください。
要件と制限事項
トランザクションを使用する前に、次の要件と制限に注意してください。
トランザクションには、レプリカセットやシャーディングされたクラスターなどのマルチドキュメントトランザクションをサポートするMongoDB Server の配置が必要です。アプリケーションがスタンドアロン配置でトランザクションを開始しようとすると、プロバイダーは をスローします。これを防ぐには、「
NotSupportedExceptionAutoTransactionBehavior.Never暗黙的なトランザクションの構成 」で説明されているように を設定します。FS コア プロバイダーは、
System.Transactions.TransactionScopeによって作成されたトランザクションなど、 .NET の環境トランザクションをサポートしていません。環境トランザクションを使用しようとすると、プロバイダーは例外をスローします。代わりに暗黙的なトランザクションまたは明示的なトランザクションを使用してください。
暗黙的なトランザクション
デフォルトでは 、FS コアプロバイダーは、複数のルートエンティティが影響を受ける場合、トランザクション内のSaveChanges() 呼び出しとSaveChangesAsync() 呼び出しを自動的にラップします。ルート エンティティは、別のドキュメント内に保存される所有型または埋め込み型とは対照的に、コレクション内の最上位ドキュメントです。
次の例では、1 回の SaveChanges() 呼び出しで 2 つの惑星を挿入しています。この操作は複数のルート エンティティに影響するため、プロバイダーは自動的にトランザクションにラップします。いずれかの挿入に失敗した場合、プロバイダーは両方の変更をロールバックします。
SynchronousAsynchronous対応するコードを表示するには、 タブまたは タブを選択します。
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() 呼び出しやその他の操作を 1 つのアトミックな作業単位にグループ化できます。明示的なトランザクションを開始するには、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();
Tip
手動ロールバック
このページの例では、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を実行する必要がある場合、 エラーが返される可能性があります。このような場合、F Core プロバイダーはトランザクションを自動的に再試行しません。一時的なトランザクションエラーと再試行戦略の詳細については、「 トランザクションエラーの処理 」を参照してください。
詳細情報
このガイドの概念の詳細については、次のリソースを参照してください。
このガイドで使用されているメソッドの詳細については、次の.NET APIドキュメントを参照してください。