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()因此我不需要为ServiceExceptionHandlerand附加处理程序ExceptionHandler

我当前的解决方案在 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 回答