ServiceStack.net中的Howto Ambient事务

时间:2013-07-16 09:03:18

标签: .net entity-framework transactions servicestack

我正在使用ServiceStack.net开发服务器应用程序。数据库通过EntityFramwork访问。现在我希望有一个Ambient Transaction,如果没有错误/异常会自动提交,否则应该丢弃更改。

我还没有找到一些尚未找到的东西,或者我是否需要自己推出?

如果我必须自己动手,我应该怎么做?首先想到的是请求和响应过滤器。

2 个答案:

答案 0 :(得分:2)

我已经使用请求和响应过滤器来设置环境事务(在我的情况下实际上是一个NHibernate会话,但这是一个类似的想法)。我们通过在AppHost的RequestFilters方法中添加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);
};

答案 1 :(得分: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();
            }
        });
}