あるクラスがIDisposableインターフェースを実装している場合、そのインスタンスが不要になったときは、必ずDispose()メソッドを呼び出す必要があります。通常は、catch節やfinally節から、あるいは呼び出し元のDispose()ルーチンから呼び出します。Dispose()は、オペレーティングシステムのオブジェクト(.NETランタイムには管理されていないもの)のようなアンマネージドリソースを解放し、マネージドリソースの内部状態をリセットするための機会になります。
別のチームが用意したデータベースの上に、ORM(Object Relational Mapping)システムを実装します。
このデータベースは、一度に1つのトランザクションだけを処理できます。
この段階では、ログ出力やその他のエラー処理は必要ありません。
内部的には、データベースはいくつかの状態を遷移することに注意してください。Closed、TransactionStarted、DataWritten、Invalid、Closedです。各演習の開始時点では、データベースがClosed状態にあると考えてかまいません。
データベースには、次のインスタンスメソッドがあります。
Database.BeginTransaction()は、データベース上でトランザクションを開始します。データベースがClosed状態でないときにこれを呼び出すと、例外がスローされます。成功すると、データベースの内部状態はTransactionStartedに変わります。Database.Write(string data)は、トランザクション内でデータベースにデータを書き込みます。不正なデータを受け取ると、例外がスローされます。BeginTransaction()を呼び出さずにこのメソッドを呼び出そうとすると、例外がスローされます。成功すると、データベースの内部状態はDataWrittenに変わります。Database.EndTransaction()は、トランザクションをデータベースにコミットします。トランザクションを閉じられない場合や、Database.BeginTransaction()が呼び出されていなかった場合には、例外をスローすることがあります。Database.Dispose()を呼び出すと、トランザクション中に例外がスローされたときにデータベースをクリーンアップします。これにより、データベースの状態はClosedに変わります。データベースの状態には、database.DbStateを使ってアクセスできます。
データベースの状態は、次のいずれかに設定できます。
Orm.Begin()を実装して、データベース上でトランザクションを開始します。データベースの内部状態がState.Closedで始まっていない場合は、InvalidOperationExceptionをスローします。
var orm = new Orm(new Database());
orm.Begin();
// => database has an internal state of State.TransactionStarted
Orm.Write()を実装して、データベースにデータを書き込みます。データベースの内部状態がState.TransactionStartedで始まっていない場合、または不正なデータが書き込まれた場合は、InvalidOperationExceptionがスローされます。書き込みが失敗したら、Ormはデータベースをクリーンアップしなければなりません。
var orm = new Orm(new Database());
orm.Begin();
orm.Write("some data");
// => database has an internal state of State.DataWritten
orm.Write("bad write");
// => database has an internal state of State.Closed
Orm.Commit()を実装して、データをコミットします。コミットが失敗したら、データベースをクリーンアップします。データベースの内部状態がState.DataWrittenで始まっていない場合は、InvalidOperationExceptionがスローされます。
var orm = new Orm(new Database());
orm.Begin();
orm.Write("some data");
orm.Commit();
// => database has an internal state of State.Closed
orm.Begin();
orm.Write("bad commit");
orm.Commit();
// => database has an internal state of State.Closed
OrmクラスにIDisposableインターフェースを実装します。この呼び出しは必ず成功します。
var db = new Database();
var orm = new Orm(db);
orm.Begin();
orm.Write("some data");
orm.Dispose();
// => database has an internal state of State.Closed