3

アプリケーションがトリガーを実行する必要があるレガシーアプリに対してレコードを保存している場合、トリガーを実行しないようにデータベースに通知できるように、winforms アプリケーションから Context_info を設定する必要があります。私が読んだことはすべて、データコンテキストを使用して設定する必要があると言っています。

私のアプリケーションでは、エンティティ マネージャーを使用しています。データ コンテキストの代わりにエンティティ マネージャーを使用してデータ コンテキストを設定するにはどうすればよいですか。トリガーが設定されているデータを実行して保存しているアプリであることをトリガーに認識させたいだけです

私は次のようにしたい。"context_info '0x1234' を設定します

トリガーの開始時に、context_info が設定されているかどうかを確認し、トリガーを実行しません。レガシーは context_info を設定しません。

4

2 に答える 2

3

アプリでもこれと同じことを行う必要がありました。Kim が述べたように、Dev Force フォーラムには多くの情報があります。このフォーラムの投稿で私たちが行ったことの完全な説明を見つけることができますが、参考のために重要な部分をここに再現します...

私たちのアプリケーションにも同様の要件がありました。私たちの場合、DB 接続が開かれるたびにカスタム ストアド プロシージャを呼び出す必要がありました。現在のユーザーを知る必要がある多くのトリガーがあるため、プロシージャは現在アクティブなユーザーとの接続を「マーク」します ( context_info を使用してこの「マーキング」を実現します)。

これは、 EF Provider Wrapper Toolkitの助けを借りて処理することができました(現在Nugetにもあるようです)。これにより、基本的に、さまざまな ADO.NET オブジェクトに独自のロジックを挿入できます。したがって、データベース アクセスの最も低いレベルで使用できます。次に、DevForce/EntityFramework が最終的に使用する独自のカスタム DbConnection クラスを作成しました。実際には非常に簡単で、非常に便利なデータベースアクセスの最下位レベルへの多くの優れた「フック」を提供してくれました。

カスタム 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, do our logic to prep the connection
        SetContextInfo();

        //...and we do some other stuff not relevant to this discussion
    }

    /// <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....

        base.Close();
    }

    /// <summary>
    /// Attempts to set context_info to the current connection if the user is 
    /// logged in to our application.
    /// </summary>
    private void SetContextInfo()
    {
        //See if a user is logged in
        var user = Thread.CurrentPrincipal as OurCustomUserType;

        //If not, we don't need to do anything - this is probably a very early call in the application
        if (user == null)
            return;

        //Create the ADO.NET command that will call our stored procedure
        var cmd = CreateCommand();
        cmd.CommandType = CommandType.StoredProcedure;
        cmd.CommandText = "p_prepare_connection_for_use";

        //Set the parameters based on the currently logged in user
        cmd.CreateParameter("as_session_id", user.SessionID, null, DbType.Guid);
        cmd.CreateParameter("ai_user_sid", user.UserID, null, DbType.Int32);

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

EF6 以降では、データベース呼び出しをインターセプトするためのよりクリーンな方法があるかもしれません....しかし、このアプローチは何年もうまく機能しています。

于 2014-06-20T20:50:45.710 に答える
0

IdeaBlade フォーラムは新しい活動に対して閉鎖されていますが、依然として検索可能であり、多くの場合、DevForce の問題に関する役立つ回答や情報が含まれています。この場合、そこで context_info を検索すると、役立つスレッドがいくつか見つかります。特に、EF Provider Wrapper ToolkitまたはEF 6 DbCommandInterceptorを使用して context_info を操作する方法を示します。これらは DbContext を必要としません。

于 2014-06-11T21:44:08.530 に答える