2012-04-18 5 views
6

SQL ServerのSQLテーブルからC#で列情報を取得しようとしています。私はこのリンクの例に従っています:http://support.microsoft.com/kb/310107私のプログラムは接続を閉じようとすると不思議にハングアップします。接続が閉じられていない場合、プログラムは例外なしで終了します。またCommandBehavior.KeyInfoCommandBehavior.SchemaOnlyに変更されない限り、アプリケーションがハングアップしSqlConnectionオブジェクトを閉じるときにアプリケーションがハングするのはなぜですか?

SqlConnection connection = new SqlConnection(@"MyConnectionString"); 
connection.Open(); 
SqlCommand command = new SqlCommand("SELECT * FROM MyTable", connection); 
SqlDataReader reader = command.ExecuteReader(CommandBehavior.KeyInfo); // If this is changed to CommandBehavior.SchemaOnly, the program runs fast. 
DataTable table = reader.GetSchemaTable(); 
Console.WriteLine(table.Rows.Count); 
connection.Close(); // Alternatively If this line is commented out, the program runs fast. 

使用してブロック内SqlConnectionを置く:ここに私のコードです。

using (SqlConnection connection = new SqlConnection(@"MyConnectionString")) 
{ 
    connection.Open(); 
    SqlCommand command = new SqlCommand("SELECT * FROM MyTable", connection); 
    SqlDataReader reader = command.ExecuteReader(CommandBehavior.KeyInfo); // If this is changed to CommandBehavior.SchemaOnly, the program runs fast even here in the using 
    DataTable table = reader.GetSchemaTable(); 
    Console.WriteLine(table.Rows.Count); 
} 

問題のテーブルには、300万行を持っているが、私は唯一のスキーマ情報を取得しておりますので、私はこれは問題ではないと思うだろう。私の質問です:接続を閉じようとしているときに私のアプリケーションが立ち往生しないのはなぜですか?

解決策:これは最適ではないかもしれませんが、動作します。私はCloseは、接続で呼び出される直前command.Cancel();文を挿入:

SqlConnection connection = new SqlConnection(@"MyConnectionString"); 
connection.Open(); 
SqlCommand command = new SqlCommand("SELECT * FROM MyTable", connection); 
SqlDataReader reader = command.ExecuteReader(CommandBehavior.KeyInfo); // If this is changed to CommandBehavior.SchemaOnly, the program runs fast. 
DataTable table = reader.GetSchemaTable(); 
Console.WriteLine(table.Rows.Count); 
command.Cancel(); // <-- This is it. 
connection.Close(); // Alternatively If this line is commented out, the program runs fast. 
+0

クローズ処理を長くする可能性のある他の変数を設定しているかどうかを確認するために、接続文字列(重要な情報のlilkeユーザー名、パスワード、サーバー、データベースは除きます)を共有できますか。 –

+0

確かに。 @ " データソース= ****; 初期カタログ= ****; ユーザーID = ****; パスワード= ****; 接続タイムアウト= 60;" –

+0

最初に読者を閉じてはいけませんか? – Deb

答えて

6

私はずっと前にこれを見ました。私のために、私は次のようなことをしたからです:

SqlCommand command = new SqlCommand("SELECT * FROM MyTable", connection); 
SqlDataReader reader = command.ExecuteReader(); 

// here, I started looping, reading one record at a time 
// and after reading, say, 100 records, I'd break out of the loop 

connection.Close(); // this would hang 

問題は、コマンドが完了したように見えるということです。つまり、結果セット全体を調べます。私の結果セットには何百万というレコードが含まれていました。結局は終わるだろう...結局のところ。

私はこの問題をcommand.Cancel()に呼び出し、connection.Close()を呼び出す前にこの問題を解決しました。

詳細については、http://www.informit.com/guides/content.aspx?g=dotnet&seqNum=610を参照してください。

+0

これは有望ですね。私は仕事に着くときにそれを試してみましょう。ありがとう! –

0

あなたはこれを試してもらえますか? SMO(SQL Server管理オブジェクト)を使用して、MSDNから

DataTable dt = new DataTable(); 
using(SqlConnection conn = new SqlConnection("yourConnectionString")) 
{ 
    SqlCommand cmd = new SqlCommand("SET FMTONLY ON; " + yourQueryString + "; SET FMTONLY OFF;",conn); 
    conn.Open(); 
    dt.Load(cmd.ExecuteReader()); 
} 

SET FMTONLY ON/OFF

+0

MSDNが「この機能を使用しないでください」というメッセージがSQL Server 2012(http://msdn.microsoft.com/en-us/library/ms173839%28v=sql)に記載されている以外は、「SET FMTONLY ON」と表示されます.110%29.aspx)。当分の間、私のアプリケーションはSQL Server 2008とのインターフェイスになりますが、近い将来に移行する可能性があるので、将来的にはそれが必要です。 –

+0

私がここで読むことができるもの[SqlServer 2012の非推奨機能](http://technet.microsoft.com/en-us/library/ms143729(v = sql.110).aspx)SET FMTONLYは引き続きサポートされており、 SQLServer__の将来のバージョンで削除されました。つまり、SQLServer 2014を意味しますか?おそらくこの声明を持っているでしょう。 – Steve

+0

CommandBehavior.SchemaOnlyは、SET FMTONLY ONのクエリに接頭辞を付けます。この値がSQLのバージョンに依存しているかどうかわかりません。私。 FMTONLYが将来のバージョンで廃止予定の場合、.NETは接続/接続文字列を介してそれを検出し、バージョンに応じた別の操作を実行しますか? – ulty4life

0

を移動するための方法を思わこれを行うための具体的な方法があり、

あなたには、テーブルのコレクションを取得することができます(列、キー、および想像できるすべてのプロパティ)

これは、SSMSがすべてのデータベースのプロパティを取得および設定するために使用するものですbjects。このリファレンスで

ルック:

これは、テーブルのプロパティを取得する方法の完全な例です:

これにより、データベースからすべての可能な情報を簡単に取得できます。 VB.NETとC#にはたくさんのサンプルがあります。

+0

私は明確に指定していないと思います私の質問が、私は選択リストの集計計算を含む可能性のあるクエリの列情報を見つけることに興味があります。したがって、テーブルの情報は不十分で、おそらく私の場合に与える限られた利益よりもむしろ問題になります。 –

0

私はこのようなものを試します。これにより、すべてのアイテムがクリーンアップされ、DataReaderの使用が回避されます。メモリの問題を引き起こすような異常な大量のデータがない限り、これは必要ありません。

public void DoWork(string connectionstring) 
    { 
     DataTable dt = new DataTable("MyData"); 
     using (var connection = new SqlConnection(connectionstring)) 
     { 
      connection.Open(); 
      string commandtext = "SELECT * FROM MyTable"; 

      using(var adapter = new SqlDataAdapter(commandtext, connection)) 
      { 
       adapter.Fill(dt); 
      } 
      connection.Close(); 
     } 
     Console.WriteLine(dt.Rows.Count); 
    } 
+0

基本的には、集計などを含む分析的なSQLクエリがいくつかあります。返される値の列名と型をすばやく判別する必要があります。それはあなたのコードのように私は全体の結果セットを取得しているように見えます。私のクエリでは何百万もの行が返される可能性があるため、これは受け入れられません。私は列のメタデータだけに興味があります。 –

+0

独自のクエリをそこに配置する必要があります。情報スキーマを使用してみてください。 select * from INFORMATION_SCHEMA.COLUMNS TABLE_NAMEは 'mytable'のようになります – tsells

関連する問題