5

Web アプリから SQL Server 2005 への接続を開くと、次のエラーが表示されることがあります。

「Impersonate Session Security Context」は同時バッチで呼び出されたため、このバッチでは呼び出すことができません。

MARS と接続プーリングを使用します。

例外は、次のコードから発生します。

protected SqlConnection Open()
{
    SqlConnection connection = new SqlConnection();
    connection.ConnectionString = m_ConnectionString;
    if (connection != null)
    {
        try
        {
            connection.Open();
            if (m_ExecuteAsUserName != null)
            {
                string sql = Format("EXECUTE AS LOGIN = {0};", m_ExecuteAsUserName);
                ExecuteCommand(connection, sql);
            }
        }
        catch (Exception exception)
        {
            connection.Close();
            connection = null;
        }
    }
    return connection;
}

EXECUTE AS LOGIN コマンドが送信される前に前のコマンドがまだ終了していない場合にエラーが発生することを示唆するMS Connectの記事を見つけました。しかし、接続が開かれたばかりの場合、これはどうしてでしょうか?

これは、接続プーリングが MARS と奇妙に相互作用していることと関係があるのでしょうか?

更新: 短期的には、これが発生するたびに接続プールをクリアすることで回避策を実装しました。これにより、さまざまなユーザーに引き渡され続けるため、接続不良を取り除くことができます。(これは現在、少数の同時ユーザーのみで 1 日に 5 ~ 10 回発生しているため、かなり面倒です。) しかし、さらにアイデアがある場合は、まだ実際の解決策を探しています...

4

3 に答える 3

2

接続プールのせいにしないでください-MARSは大混乱を引き起こしたことで非常に有名です。それは完全に非難ではありませんが、それは一種の半分です。覚えておくべき重要なことは、MARSは設計されており、「通常の」DB使用でのみ機能することです(つまり、通常のCRUDは管理バッチを使用しません)。DBエンジンに幅広い影響を与えるコマンドは、1つの接続とシングルスレッド(セットアップバッチを実行してテーブルやネストされたトランザクションを作成するなど)であっても、MARSをトリップする可能性があります。

そうは言っても、MARSのせいにするのは簡単ですが、99%のような通常のCRUDシナリオでは完全にうまく機能します(ORM-sやLINQのような効率の低いものは一生依存します)。つまり、接続を介してSQLをハッキングしたい場合、MARSを使用できないことを人々が学ぶことが重要です。たとえば、DB全体を最初から作成するセットアップコードがありました。これは、デプロイに非常に便利なためですが、デプロイしているWebサービスと接続を共有していました-おっと:-)レッスンを学ぶために数日掘り下げました。だから私は関心の分離を維持し(これは常に良いことです)、問題はなくなりました。

于 2010-08-06T11:12:17.793 に答える
2

プーリングではなくMARSだと思います

複数のアクティブな結果セット (MARS) の使用」より

  • アプリケーションは、複数の既定の結果セットを開くことができ、それらからの読み取りをインターリーブできます。
  • アプリケーションは、既定の結果セットが開いている間に、他のステートメント (INSERT、UPDATE、DELETE、ストアド プロシージャの呼び出しなど) を実行できます。

基本的な形式の接続プーリングは、接続のオープン/クローズのオーバーヘッドが最小限に抑えられることを意味しますが、どの接続でも (MARS まで) 常に 1 つの処理が行われます。プーリングはしばらく前から存在しており、箱から出してすぐに機能します。

MARS(ところで、私はそれを使用していません)は、単一の接続に対して重複する「もの」を導入します。したがって、接続プールではなく、おそらく MARS が 2 の大きな原因です。

EXECUTE AS を使用してデータベース偽装を拡張する」より

EXECUTE AS LOGIN ステートメントを使用してプリンシパルを偽装する場合、または EXECUTE AS 句を使用してサーバー スコープのモジュール内で偽装する場合、偽装のスコープはサーバー全体になります。

これは、MARS が原因である理由を説明している可能性があります。2 つのセッションで同じプリンシパルが両方とも EXECUTE AS を実行しています。その使用記事に何かがあるかもしれません、またはこれを試してください:

IF ORIGINAL_LOGIN() = SUSER_SNAME() EXECUTE AS LOGIN = {0};

熟考し、この回答を読んだ後、1​​つの接続で各セッション(MARS)の実行コンテキストを変更しようとすることは良い考えだとは確信していません...

于 2010-03-30T18:17:28.230 に答える
0

SQLステートメントの最後で復帰を使用しようとしましたか?

http://msdn.microsoft.com/en-us/library/ms178632.aspx

私は常にこれを行って、現在のコンテキストが正常に戻っていることを確認します。

于 2010-08-05T12:52:00.513 に答える