SqlConnection 在关闭之前的事件是什么?

3
我想知道是否有一种事件可以处理,该事件会在SqlConnection关闭之前触发,例如:OnBeforeClose?我的目标是在SQL Server中调用sp_unsetapprole,以便在连接关闭并返回到连接池时不再附加任何approle。
起初我认为可以处理StateChange事件,但我认为此时已经为时过晚。
目前对我来说唯一的解决方法是在SqlConnection调用程序上手动调用sp_unsetapprole。
非常感谢您的关注和时间!
YS.

如果您的应用程序崩溃并且连接根本没有关闭怎么办?悬挂角色? - Uwe Keim
@UweKeim - 你会收到“SQL错误 - 当前命令发生严重错误。如果有任何结果,应该被丢弃。” - YS.
2个回答

2
当事件触发时,运行任何类型的SQL批处理都太晚了。我建议您遵循MSDN关于此主题的建议:
在通过调用sp_setapprole系统存储过程激活SQL Server应用程序角色之后,该连接的安全上下文无法重置。但是,如果启用了池化,则将连接返回到池中,并在重复使用池化连接时出现错误。
当提出这样的建议时,试图违背它们通常是一个坏主意。你可以放弃应用程序角色,有更好的替代方案
应用程序角色依赖于密码的安全性,这可能会导致潜在的安全漏洞。密码可能会因为被嵌入应用程序代码或保存在磁盘上而被暴露。您可以考虑以下替代方案: 1. 使用EXECUTE AS语句进行上下文切换,并使用其NO REVERT和WITH COOKIE子句。您可以在未映射到登录名的数据库中创建一个用户帐户。然后,您为此帐户分配权限。使用不带登录名的用户执行EXECUTE AS更加安全,因为它是基于权限而不是密码的。有关详细信息,请参阅在SQL Server中使用模拟自定义权限。 2. 使用证书签署存储过程,仅授予执行存储过程的权限。有关详细信息,请参见在SQL Server中签署存储过程

感谢您尝试回答我的问题。不幸的是,我没有看到您回答我的问题。即使是您分享的MSDN建议,也与SQL Server自己的功能“该连接的安全上下文无法重置”相矛盾,同时他们引入了sp_unsetapprole。我只是想找到一种在.Close方法中执行sp_unsetapprole的方法。SqlConnection作为一个密封类也没有帮助。 - YS.
1
我很感激你提供了应用角色的替代方案。对此给予一个赞,但是我不能接受这个答案,因为这是一个遗留系统,重写以使用其中一种替代方案可能需要很大的工作量。 - YS.

1
我知道现在有点晚了,但是我看到这个答案并想提供另一个选项。我们的应用程序有一个非常类似的需求。我们需要在每次连接打开和关闭时调用自定义存储过程。
我们使用EF Provider Wrapper Toolkit(现在也可以在Nuget上找到)来处理这个问题。基本上,它允许您将自己的逻辑注入到各种ADO.NET对象中 - 因此在最低级别的数据库访问中。然后,我们制作了自己的自定义DbConnection类,您的应用程序中的任何代码都将使用它。实际上很容易,而且为我们提供了很多有用的“钩子”,可以方便地访问最低级别的数据库访问。
请注意,我们正在使用Entity Framework,该库称为EF Provider Wrapper Toolkit,但它与使用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();
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接