3

我想知道是否有一个事件我可以在 SqlConnection 关闭之前处理事件触发的地方,即:OnBeforeClose ?我想要实现的是 -sp_unsetapprole在 SQL Server 中调用,以便在连接关闭并返回连接轮询时 - 所以它没有附加任何应用程序。

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

我目前的解决方法是手动调用sp_unsetapproleSqlConnection 调用者。

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

是的。

4

2 回答 2

2

当事件触发时为时已晚,无法运行任何类型的 SQL 批处理。我建议您遵循有关该主题的 MSDN 建议

通过调用 sp_setapprole系统存储过程激活 SQL Server 应用程序角色后,无法重置该连接的安全上下文。但是,如果启用了池化,则将连接返回到池中,并且在重新使用池化连接时会发生错误。

当提出这样的建议时,试图反对它们通常是一个坏主意。你可以放弃应用角色,还有更好的选择

应用程序角色替代

应用程序角色依赖于密码的安全性,这会带来潜在的安全漏洞。密码可能会通过嵌入应用程序代码或保存在磁盘上而暴露。您可能需要考虑以下替代方案:

  • 使用带有 NO REVERT 和 WITH COOKIE 子句的 EXECUTE AS 语句进行上下文切换。您可以在未映射到登录名的数据库中创建用户帐户。然后,您将权限分配给此帐户。对无登录用户使用 EXECUTE AS 更安全,因为它是基于权限的,而不是基于密码的。有关详细信息,请参阅在 SQL Server 中使用模拟自定义权限

  • 使用证书签署存储过程,仅授予执行过程的权限。有关详细信息,请参阅在 SQL Server 中签署存储过程

于 2012-07-31T10:02:21.557 回答
1

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

我们能够在EF Provider Wrapper Toolkit的帮助下处理这个问题(现在似乎也在Nuget上)。这基本上可以让您将自己的逻辑注入到各种 ADO.NET 对象中——因此在数据库访问的最低级别。然后,我们创建了自己的自定义 DbConnection 类,您的应用程序中的任何代码最终都将使用该类。它实际上非常简单,并且为我们提供了很多很好的“挂钩”到最低级别的数据库访问,这些都派上了用场。

请注意,我们使用的是实体框架,该库称为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();
    }
}
于 2016-07-06T18:01:49.350 回答