1

ServiceStack.net を使用してサーバー アプリケーションを開発しています。データベースには、EntityFramwork 経由でアクセスします。ここで、エラー/例外がない場合に自動的にコミットされるアンビエント トランザクションが必要です。それ以外の場合は、変更を破棄する必要があります。

箱から出してまだ見つけていないものはありますか、それとも自分で作成する必要がありますか?

自分でロールする必要がある場合、どうすればよいですか? 最初に思い浮かぶのは、リクエスト フィルタとレスポンス フィルタです。

4

2 に答える 2

2

リクエストとレスポンスのフィルターを使用してアンビエント トランザクションをセットアップしました (実際には、私の場合は NHibernate セッションですが、考え方は似ています)。これは、AppHost のメソッドのRequestFiltersandコレクションに追加することで実現しました。ResponseFiltersConfigure

また、成功した場合にトランザクションをコミットすることと、エラーが発生した場合にトランザクションをロールバック/クリアすることを区別する必要がありました。

// normally: commit the transaction
ResponseFilters.Add((req, res, dto) => DbConnectionUtility.CleanupTransactionsAndConnections(req.RawUrl));

// rollback if unhandled exception in a service method
ServiceExceptionHandler = (request, exception) =>
{
    DbConnectionUtility.ClearSessions();
    // run the default code that sends a nicely serialized error response
    return DtoUtils.HandleException(this, request, exception);
};

// rollback if unhandled exception outside of service (e.g. in a filter)
var defaultExceptionHandler = ExceptionHandler;
ExceptionHandler = (httpReq, httpRes, operationName, ex) =>
{
    DbConnectionUtility.ClearSessions();
    // run the default code that sends a nicely serialized error response
    defaultExceptionHandler(httpReq, httpRes, operationName, ex);
};
于 2013-07-17T16:19:53.793 に答える
1

@esker私を正しい方向に向けてくれてありがとう

TransactionScopeデフォルトでは、 が呼び出されない場合はロールバックされるため、 およびComplete()のハンドラーをアタッチする必要はありません。ServiceExceptionHandlerExceptionHandler

私の現在のソリューションは、AppHost ファイルで次のようになります。

public void ConfigureFilters(Container container)
{
    RequestFilters.Add(
        (req, res, dto) =>
        req.Items.Add("transaction", new TransactionScope(TransactionScopeOption.RequiresNew)));

    ResponseFilters.Add((req, res, dto) =>
        {
            TransactionScope transaction = null;
            var error = dto as HttpError;
            try
            {
                transaction = req.Items["transaction"] as TransactionScope;
                if (error == null)
                {
                    container.Resolve<TierDbEntitiesContainer>().SaveChanges();
                    if (transaction == null) 
                        throw new AmbientTransactionException("Transaction not found.");
                    transaction.Complete();
                }
            }
            finally
            {
                if (transaction != null)
                    transaction.Dispose();
            }
        });
}
于 2013-07-18T12:18:23.917 に答える