SqlConnection On Close事件?

时间:2012-07-31 05:20:39

标签: c# sql-server sqlconnection

我想知道是否有一个事件可以处理事件在SqlConnection关闭之前触发的位置,即:OnBeforeClose?我想要实现的是 - 在SQL Server中调用sp_unsetapprole,以便在连接关闭并返回到连接轮询时 - 因此它没有附加的关联。

起初我以为我可以处理StateChange事件 - 但我相信已经太晚了。

我目前的解决方法是在SqlConnection调用方上手动调用sp_unsetapprole

非常感谢您的关注+时间!

YS。

2 个答案:

答案 0 :(得分:2)

当事件触发时太晚,无法运行任何类型的SQL批处理。我建议您按照MSDN recommendation on the subject

进行操作
  

通过调用激活SQL Server应用程序角色后   sp_setapprole系统存储过程,即安全上下文   连接无法重置。但是,如果启用了池,则   连接返回到池,并在发生时发生错误   汇集连接被重用。

当提出这些建议时,试图反对它们通常是一个坏主意。您可以放弃应用角色there are better alternatives

  

应用程序角色替代

     

应用程序角色取决于密码的安全性   潜在的安全漏洞。密码可能会被暴露   嵌入应用程序代码或保存在磁盘上。您可能需要考虑以下备选方案:

     
      
  • 将上下文切换与EXECUTE AS语句及其NO REVERT和WITH COOKIE子句一起使用。您可以在中创建用户帐户   未映射到登录的数据库。然后,您可以分配权限   此帐户。将EXECUTE AS与无登录用户一起使用会更安全   因为它是基于权限的,而不是基于密码的。更多   信息,请参阅Customizing Permissions with Impersonation in SQL Server

  •   
  • 使用证书对存储过程进行签名,仅授予执行过程的权限。有关详细信息,请参阅Signing Stored Procedures in SQL Server

  •   

答案 1 :(得分:1)

我知道这已经很晚了,但我遇到了这个答案,并想在那里抛出另一个选项。我们的申请要求非常相似。我们需要在每次打开连接时调用自定义存储过程,并在关闭时再次调用。

我们能够在EF Provider Wrapper Toolkit的帮助下处理这个问题(现在似乎也在Nuget上)。这基本上允许您将自己的逻辑注入到各种ADO.NET对象中 - 因此在最低级别的数据库访问中。然后我们制作了自己的自定义DbConnection类,您的应用中的任何代码都将最终使用。它实际上非常简单,并且在最低级别的数据库访问中给了我们很多很好的“钩子”,它们已经派上了用场。

请注意,我们使用的是实体框架,该库名为 EF 提供程序包装工具包,但它适用于使用ADO.NET访问数据库的任何代码。

以下是我们的自定义DbConnection类的示例代码,它显示了您可以完成的各种事情:

/// <summary>
/// Custom implementation of a wrapper to <see cref="DbConnection"/>.
/// Allows custom behavior at the connection level.
/// </summary>
internal class CustomDbConnection : DbConnectionWrapper
{
    /// <summary>
    /// Opens a database connection with the settings specified by 
    /// the <see cref="P:System.Data.Common.DbConnection.ConnectionString"/>.
    /// </summary>
    public override void Open()
    {
        base.Open();

        //After the connection has been opened, use this spot to do any initialization type logic on/with the connection

    }

    /// <summary>
    /// Closes the connection to the database. This is the preferred method of closing any open connection.
    /// </summary>
    /// <exception cref="T:System.Data.Common.DbException">
    /// The connection-level error that occurred while opening the connection.
    /// </exception>
    public override void Close()
    {
        //Before closing, we do some cleanup with the connection to make sure we leave it clean
        //   for the next person that might get it....

        CleanupConnection();

        base.Close();
    }

    /// <summary>
    /// Cleans up the connection so the next person that gets it doesn't inherit our junk.
    /// </summary>
    private void CleanupConnection()
    {
        //Create the ADO.NET command that will call our stored procedure
        var cmd = CreateCommand();
        cmd.CommandType = CommandType.StoredProcedure;
        cmd.CommandText = "p_cleanup_connection";

        //Run the SP
        cmd.ExecuteNonQuery();
    }
}