如何使用ABP框架中的拦截器包装工作单元

时间:2017-09-30 01:12:45

标签: unit-of-work aspnetboilerplate

文章https://www.codeproject.com/Articles/1080517/Aspect-Oriented-Programming-using-Interceptors-wit的作者正在解释如何在" ASPNET Boilerplate"中创建一个拦截器。框架。在我的例子中,我想创建一个拦截器(或两个拦截器,一个用于Start,另一个用于End),它将包裹Unit of Work。当任何spStart中的方法启动时,我需要调用名为AppService的存储过程,并在调用数据库时调用spEnd。由于ABP中的Unit of Work也是一个拦截器,这是我迄今为止所做的: 按照文章中的步骤我提供了上面的链接,我做了以下内容:

  • 添加了两个拦截器:StartInterceptorEndInterceptor 他们的Registrar班级
  • ApplicationModule班级
  • 中注册
  • 同样在ApplicationModule我添加了以下代码:

    IocManager.IocContainer.Register(Component.For<IApplicationService>() .Interceptors(InterceptorReference.ForType<StartInterceptor>()).First, Component.For<StartInterceptor>() .Interceptors(InterceptorReference.ForType<EndInterceptor>()).Last, Component.For<StopInterceptor>());

此代码应首先运行StartInterceptor,最后运行EndInterceptor。考虑到工作单元拦截器介于两者之间,并且我们将使用逻辑来等待截获的异步方法以返回结果,这应该为我们提供了包装工作单元的选项。然而,这就是:当spStart运行时,一切正常。这个存储过程在Unit of Work拦截器之前运行,因此没有问题。但是,当spEnd运行时,它表示&#34;应该在连接可用于执行SQL语句之前处理事务&#34;或&#34;该操作对事务状态无效&#34; ...似乎UoW与我的存储过程并行运行。还有其他人与ABP有同样的问题吗?你是怎么解决的?

1 个答案:

答案 0 :(得分:3)

如果遇到事务问题,您可能需要从活动连接获取活动事务。当你得到事务时,将它分配给你的sql命令。

private DbCommand CreateCommand(string commandText, CommandType commandType, params SqlParameter[] parameters)
{
    var command = Context.Database.GetDbConnection().CreateCommand();

    command.CommandText = commandText;
    command.CommandType = commandType;
    command.Transaction = GetActiveTransaction();

    foreach (var parameter in parameters)
    {
        command.Parameters.Add(parameter);
    }

    return command;
}

private void EnsureConnectionOpen()
{
    var connection = Context.Database.GetDbConnection();

    if (connection.State != ConnectionState.Open)
    {
        connection.Open();
    }
}

private DbTransaction GetActiveTransaction()
{
    return (DbTransaction)_transactionProvider.GetActiveTransaction(new ActiveTransactionProviderArgs
    {
        {"ContextType", typeof(PhoneBookDbContext) },
        {"MultiTenancySide", MultiTenancySide }
    });
}




public async Task<GetUserByIdOutput> ExecuteMyStoredProcedure(EntityDto input)
{
    EnsureConnectionOpen();

    using (var command = CreateCommand("SELECT dbo.GetUsernameById(@id)", CommandType.Text, new SqlParameter("@id", input.Id)))
    {
        var username = (await command.ExecuteScalarAsync()).ToString();
        return new GetUserByIdOutput() { Username = username };
    }
}

更多信息:https://www.codeproject.com/Articles/1199648/Using-Stored-Procedure-User-Defined-Function-and-V