[seasar-dotnet:606] ガベージコレクト発生後のS2TestCase.ReadXlsWriteDbの挙動について

Masayuki TAMADA [E-MAIL ADDRESS DELETED]
2007年 10月 12日 (金) 17:46:47 JST


初めまして。タマダと言います。

業務で利用させて貰っています。
その中でS2Unit.NETをDBに対するテストにて利用しています。

その時、テーブル数/テストケースが多い場合、ReadXlsWriteDbメソッド呼び出し時に以下の様な例外が発生する事があります。

---
項目は既に追加されています。辞書のキー: 'テーブル名' 追加されるキー: 'テーブル名'
  場所 System.Collections.Hashtable.Insert(Object key, Object nvalue, Boolean add)
  場所 System.Collections.Hashtable.Add(Object key, Object value)
  場所 Seasar.Extension.DataSets.States.CreatedState.GetSql(DataTable table)
  場所 Seasar.Extension.DataSets.States.AbstractRowState.Update(IDataSource
dataSource, DataRow row, ICommandFactory commandFactory)
  場所 Seasar.Extension.DataSets.Impl.SqlTableWriter.DoWrite(DataTable table)
  場所 Seasar.Extension.DataSets.Impl.SqlTableWriter.Write(DataTable table)
  場所 Seasar.Extension.DataSets.Impl.SqlWriter.Write(DataSet dataSet)
  場所 Seasar.Extension.Unit.S2TestCase.WriteDb(DataSet dataSet)
  場所 Seasar.Extension.Unit.S2TestCase.ReadXlsWriteDb(String path)
---

必ず発生する訳ではないので放置していたのですが、ちょっと気になったので
ソースレベルで追ってみました。

Seasar.Extension.DataSets.States.CreatedStateクラス中のGetSqlメソッド内で
WeakReferenceにて参照されるターゲット(SQL文字列)をHashtableにて管理されて
いますが、その再利用時の判定に問題がある気がします。

現在は

if (reference == null || !reference.IsAlive)
{
    sql = CreateSql(table);
    _sqlCache.Add(table, new WeakReference(sql));
}

となっています。
しかし、ガベージコレクトにてターゲットが回収済みの場合はAddメソッド呼び出し時に必ずArgumentExceptionが発生する事になります。ですので、上記は

if (reference == null)
{
    sql = CreateSql(table);
    _sqlCache.Add(table, new WeakReference(sql));
}
else if (!reference.IsAlive)
{
    reference.Taget = CreateSql(table);
}

となるべきでは無いでしょうか?

お手数ですが、確認の程宜しくお願いします。


seasar-dotnet メーリングリストの案内