2017-09-30 27 views
0

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

  • 增加了两个拦截器: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运行时,它表示“事务应在连接可用于执行SQL语句之前处理”或“该操作对于事务状态无效”......似乎UoW与我的存储过程。有没有其他人与ABP有同样的问题?你是如何解决它的?

回答

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

+0

它的工作!谢谢。 – John