2

私のWebアプリの各リクエストは、MVC3独自の依存性注入メカニズムを介して、(UnitofWorkタイプの)1つのデータアクセスオブジェクトインスタンスを取得できます。ここまでは順調ですね。

Idisposable UnitofWorkScopeオブジェクトを作成して、このデータアクセスオブジェクトのいくつかのストア呼び出しを集約し、それらを一緒に呼び出します。実際、UnitofWorkScopeはUnitofWorkオブジェクトのみを制御します。このオブジェクトには、ストアをリストに追加して後で呼び出す機能があります。UnitofWorkScopeオブジェクトは、データアクセスオブジェクトに排他的にアクセスできる必要があると思います。

ここで質問: Monitor.Enter()を使用してコンストラクターで排他ロックを取得し、Monitor.Exit()を使用してdisposeメソッドで解放することに異議を唱える人がいるのではないかと思います。

私はなぜこれを求めているのかを説明することによって水域を濁らせましたが、私がここに置いたものについては自由にコメントしてください。

public class UnitofWorkScope : IDisposable
{
    public UnitofWorkScope(UnitOfWork UnitofWork)
    {
        if (UnitofWork == null)
        {
            throw new ArgumentException("UnitofWork argument null");
        }  
        this._unitofWork = UnitofWork;
        Monitor.Enter(_unitofWork); // obtaining exclusive access to the DAO of this request
        this._unitofWork.AggregateDbChanges = true; //switched back off in dispose method
    }

    private readonly UnitOfWork _unitofWork;

    bool _disposed;

    public void Dispose(bool disposing)
    {
        if (!_disposed)
        {
            _unitofWork.CallFuncList();
            Monitor.Exit(_unitofWork); //releasing the lock
            _disposed = true;
            GC.SuppressFinalize(this);
        }
    }

    public void Dispose()
    {
        Dispose(true);
    }

    ~UnitofWorkScope()
    {
        if (!_disposed)
        {
            Dispose(false);
        }
    }
}

アイデアは、このUnitofWorkScopeを次のように使用することです。

UnitofWork _unitofWork = Resolver.GetService<UnitofWork>(); //gets the UnitofWork DAO

using (UnitofWorkScope UnitofWorkScope = new UnitofWorkScope(_unitOfWork))
{
    // do a store

    _unitofWork.Store<SomeClass>(_someInstance);

   // do some more stores 

   try
   {
        UnitofWorkScope.Dispose(true); 
   }
   catch (exception ex)
   {
     //try to undo those stores.
   }
} 
4

1 に答える 1

0

はい、これはロックを実装するための悪いパターンではありません。_unitofWork.CallFuncList()ただし、何らかのロールバックを実行する必要性を検出するために依存している例外がスローされた場合でも、ロックが解放されることを保証するために、少し異なるバージョンの Dispose をお勧めします。

private void Dispose(bool disposing) 
{ 
    if (!_disposed) 
    { 
        try
        {
            _disposed = true; 
            _unitofWork.CallFuncList(); 
        }
        finally
        {
            Monitor.Exit(_unitofWork); //releasing the lock 
            GC.SuppressFinalize(this); 
        }
    } 
} 

ただし、を明示的に呼び出す必要がないように、ロックの「解放」ロジックから「コミット」を分離したい場合がありDispose()ます。これは、using ステートメントが自動的に行います。

public void Commit()
{
    _unitofWork.CallFuncList(); 
}

private void Dispose(bool disposing) 
{ 
    if (!_disposed) 
    { 
        try
        {
            _disposed = true; 
        }
        finally
        {
            Monitor.Exit(_unitofWork); //releasing the lock 
            GC.SuppressFinalize(this); 
        }
    } 
}

その後、次のように使用できます。

using (var unitofWorkScope = new UnitofWorkScope(_unitOfWork))     
{     
    // do a store     

    _unitofWork.Store<SomeClass>(_someInstance);     

   // do some more stores      

   try     
   {     
        unitofWorkScope.Commit();
   }     
   catch (exception ex)     
   {     
     //try to undo those stores.     
   }     
}  // unitofWorkScope.Dispose() automatically called here
于 2012-07-02T16:33:58.607 に答える