コネクションプーリング を使用しても、GLOBAL な CURSOR が解放 (DEALLOCATE) される

CURSOR の宣言時に、LOCAL を指定しないと既定の動作では GLOBAL な CURSOR になります。
DECLARE CURSOR (Transact-SQL)
GLOBAL な CURSOR は CLOSE しなかった場合、接続が閉じられる迄使用可能です。
Transact-SQL カーソルの名前のスコープ
で、System.Data.Sql.SqlConnection SqlConnection クラス (System.Data.SqlClient) でコネクションプーリングを使用した場合は、GLOBAL な CURSOR が解放されるか試してみました。

ストアド (GLOBAL な CURSOR を DEALLOCATE しない)

CREATE PROCEDURE [GlobalCursorTest]
AS
BEGIN
DECLARE SampleCrsr CURSOR GLOBAL FOR 
  SELECT Name
  FROM Table_1

OPEN SampleCrsr

FETCH NEXT FROM SampleCrsr 
WHILE (@@FETCH_STATUS <> -1)
BEGIN
   FETCH NEXT FROM SampleCrsr
END

CLOSE SampleCrsr;
-- わざと CURSOR を解放しない
-- DEALLOCATE SampleCrsr;

END

GO

C#

using System;
using System.Data;
using System.Data.SqlClient;

class Program
{
  const String ConnStr = @"Data Source=<serverName>;Initial Catalog=<databaseName>;Integrated Security=True;Max Pool Size=1";
  static void Main(string[] args)
  {
    ExecGlobal();
    ExecGlobal();
    Console.ReadKey();
  }
  static void ExecGlobal()
  {
    ExecCore("[GlobalCursorTest]");
  }
  static void ExecCore(String procedureName)
  {
    try
    {
      using (var conn = new SqlConnection(ConnStr))
      using (var cmd = new SqlCommand(procedureName, conn))
      {
        conn.Open();
        cmd.CommandType = CommandType.StoredProcedure;
        cmd.ExecuteNonQuery();
        // コメントアウトを外すと例外発生
        // cmd.ExecuteNonQuery();
      }
    }
    catch (SqlException ex)
    {
      Console.WriteLine(ex.Message);
    }
  }
}

ストアドでは、GLOBAL な CURSOR を解放せずに、C# 側から呼び出しています。
C# 側から、同一接続で2回続けて呼び出すと例外が発生します。しかし、別の接続を用いて続けて呼び出しても例外が発生しません。
ってことは、コネクションプーリングを使用しても GLOBAL な CURSOR は解放されている様です。


しかし、GLOBAL な CURSOR を使わなければならない場合以外では、LOCAL を指定してる方が良さそうです。
LOCAL な CURSOR は変数のスコープ外になると、解放される様です。

Transact-SQL カーソルの名前のスコープ 引用

ローカル カーソルは、ストアド プロシージャやトリガで実装されたカーソルを保護するために重要です。グローバル カーソルは、カーソルが宣言されているストアド プロシージャまたはトリガの外部から参照できます。したがって、グローバル カーソルは、ストアド プロシージャやトリガ外部のステートメントで誤って変更される可能性があります。ローカル カーソルは、cursor 出力パラメータとして呼び出し側に意図的に渡されない限り、ストアド プロシージャ外部からは参照できないので、グローバル カーソルより高いセキュリティ保護を実現できます
〜(中略)
GLOBAL カーソルは、明示的に割り当てを解除されるか、接続が閉じられるまで使用できます。LOCAL カーソルは、LOCAL カーソルが作成されたストアド プロシージャ、トリガ、またはバッチが終了するときに、暗黙的に割り当てを解除されます。ただし、カーソルがパラメータとして渡された場合を除きます。また、LOCAL カーソルは、プロシージャを呼び出したコード内のカーソルを参照するパラメータや変数がスコープ外になったときに、暗黙的に割り当てを解除されます。

上記のストアドも、CURSOR 宣言時に GLOBAL -> LOCAL に変更すると、C# 側で同一接続から続けて呼び出しても例外が発生しません。
LOCAL は、SQL SERVER 2005 から使えるのかな?確か。