Web api-在操作过滤器中提交数据库事务

问题描述 投票:0回答:1

编辑:这个问题已经从其原始版本中被完全修改。

我的目标是在操作提交者级别提交数据库事务。我正在使用Web API .Net Framework(4.8)和Unity DI。

我的交易过滤器属性:

public class TransactionFilterAttribute : ActionFilterAttribute
{
    private readonly PortalContext _context;
    private DbContextTransaction _transactionScope;

    public TransactionFilterAttribute(IUnityContainer container)
    {
        _context = container.Resolve<PortalContext>();
    }

    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        _transactionScope = _context.Database.BeginTransaction();
        using (_transactionScope)
        {
            base.OnActionExecuting(actionContext);
        }
    }

    public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
    {
        try
        {
            base.OnActionExecuted(actionExecutedContext);
            _transactionScope.Commit(); //Error occurred
        }
        catch (Exception ex)
        {
            Debug.WriteLine(ex.ToString());
        }
    }
}

统一配置:

public static class UnityConfig
{
    private static readonly Lazy<IUnityContainer> container = new Lazy<IUnityContainer>(() =>
    {
        var container = new UnityContainer();
        RegisterTypes(container);
        return container;
    });

    public static IUnityContainer Container => container.Value;

    private static void RegisterTypes(IUnityContainer container)
    {
        container.RegisterType<PortalContext>();
    }
}

执行_transactionScope.Commit()时出现错误

错误:值不能为null。参数名称:连接->基础提供程序在提交时失败。

任何帮助将不胜感激。

c# entity-framework asp.net-web-api unity-container
1个回答
0
投票

您可以将代码更改为如下所示。这将在调用控制器时打开事务,并在提交事务之前等待方法返回。这是通过“ await next()”部分完成的。您应该从DI容器中解析_databaseContext。如果需要,请使用此方法的同步版本。

        public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
    {
        using (var transaction = _databaseContext.Database.BeginTransaction())
        {
            var result = await next();
            if ((result.Exception == null || result.ExceptionHandled) &&
                IsHttpSuccessStatusCode(context.HttpContext.Response.StatusCode))
            {
                transaction.Commit();
            }
            else
            {
                transaction.Rollback();
                var controllerActionDescriptor = context.ActionDescriptor as ControllerActionDescriptor;
                var controllerName = controllerActionDescriptor?.ControllerName;
                var actionName = controllerActionDescriptor?.ActionName;

                _logger.Error("Tried to commit transaction for the {ActionName}" +
                              " method on the {ControllerName} controller with the following parameters: {ActionParameters}" +
                              " but got exception: {Exception}",
                    actionName, controllerName, context.ActionArguments, result.Exception);
            }
        }
    }
© www.soinside.com 2019 - 2024. All rights reserved.