3

SqlConnectionが閉じる直前にイベントが発生する場所で処理できるイベントがあるかどうか疑問に思っていますOnBeforeClose 。私が達成したいのはsp_unsetapprole、SQL Serverを呼び出して、接続が閉じられて接続ポーリングに戻ったときに、approleがアタッチされていないようにすることです。

最初はStateChangeイベントを処理できると思っていましたが、もう手遅れだと思います。

私の現在の回避策はsp_unsetapprole、SqlConnection呼び出し元を手動で呼び出すことです。

あなたの注意と時間に大いに感謝します!

YS。

4

2 に答える 2

2

イベントが発生するのは遅すぎて、あらゆる種類のSQLバッチを実行できません。この件については、 MSDNの推奨事項に従うことをお勧めします。

システムストアドプロシージャを呼び出してSQLServerアプリケーションの役割をアクティブ化した後は sp_setapprole、その接続のセキュリティコンテキストをリセットできません。ただし、プーリングが有効になっている場合、接続はプールに戻され、プールされた接続が再利用されるとエラーが発生します。

そのような推奨事項が提示された場合、それらに反対しようとすることは通常悪い考えです。あなたはアプリの役割をあきらめることができます、より良い選択肢があります

アプリケーションの役割の選択肢

アプリケーションの役割はパスワードのセキュリティに依存しているため、潜在的なセキュリティの脆弱性が存在します。パスワードは、アプリケーションコードに埋め込まれたり、ディスクに保存されたりすることで公開される可能性があります。次の代替案を検討することをお勧めします。

  • NORREVERT句とWITHCOOKIE句を含むEXECUTEASステートメントでコンテキストスイッチングを使用します。ログインにマップされていないデータベースにユーザーアカウントを作成できます。次に、このアカウントに権限を割り当てます。ログインのないユーザーでEXECUTEASを使用すると、パスワードベースではなく権限ベースであるため、より安全になります。詳細については、「SQLServerでの偽装によるアクセス許可のカスタマイズ」を参照してください。

  • プロシージャを実行する権限のみを付与して、証明書を使用してストアドプロシージャに署名します。詳細については、「SQLServerでのストアドプロシージャの署名」を参照してください。

于 2012-07-31T10:02:21.557 に答える
1

私はこれが遅いことを知っていますが、私はこの答えに出くわし、そこに別のオプションを投げたかったのです。アプリケーションには非常によく似た要件がありました。接続が開かれるたびに、また接続が閉じられるときに、カスタムストアドプロシージャを呼び出す必要がありました。

EFプロバイダーラッパーツールキットの助けを借りてこれを処理することができました(これも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();
    }
}
于 2016-07-06T18:01:49.350 に答える