2011年7月13日水曜日

IStructuralEquatableの使い方

IStructuralEquatableについて今までいまいちわからずにいました。ググって出てきたページを読んでいたら使い方が微妙で違和感を覚えたためじっくり調べてみました。そうしたらもうちょっと使いやすいものだということがわかりました。
StructuralComparisons.StructuralEqualityComparerはオブジェクトそのものではなく、その要素を比較するIEqualityComparerを提供します。これを使ってIEqualityComparer<T>の実装例を書いてみました。

public class StructuralEqualityComparer<T> : IEqualityComparer<T> where T: IStructuralEquatable { public bool Equals(T x, T y) { return StructuralComparisons.StructuralEqualityComparer.Equals(x, y); } public int GetHashCode(T obj) { return StructuralComparisons.StructuralEqualityComparer.GetHashCode(obj); } }
こう書いてしまえばどう使うのかわかりやすいでしょうか。このサンプルそのものは new StructuralEqualityComparer<int[]>() のように使えます。
なんでこんなクラスをわざわざ作るのかというと、LINQで要求される比較演算子はどれもIEqualityComparerでなくIEqualityComparer<T>だからです。

2011年2月1日火曜日

TransactionScope classの使い方

.NET Frameworkでtransactionを扱うにはTransactionScope classを使いますが、嵌りやすいのでメモっておきます。

class説明にはisolation levelについて記載されていませんが、デフォルトではSerializableになっています。例えばSQL ServerのデフォルトはReadCommittedなので勘違いしてしまいそうです。では、isolation levelを指定しようとすると、constructorにもpropertyにもそれらしいものがありません。実はpublic TransactionScope( TransactionScopeOption scopeOption, TransactionOptions transactionOptions )のTransactionOption classで指定することになります。 しかし今度は余計なparameterまで渡す必要があります。

  • TransactionScopeOption…これはRequiredがデフォルトです。
  • TransactionOptionsのIsolationLevel…これは指定したかったReadCommittedにします。
  • TransactionOptionsのTimeout…これは指定しないと初期化されず0になってしまい、timeoutなしになってしまいます。デフォルトの値にするためにはTransactionManager.DefaultTimeoutを指定します。
結局、
using( var transaction = new TransactionScope( TransactionScopeOption.Required, new TransactionOptions{ IsolationLevel = IsolationLevel.ReadCommitted, Timeout = TransactionManager.DefaultTimeout, } ) ){ ...; transaction.Complete(); }
とやることになるでしょう。