7

SQL Server の SQL テーブルから C# で列情報を取得しようとしています。このリンクの例に従っています: http://support.microsoft.com/kb/310107接続を閉じようとすると、プログラムがハングアップします。接続が閉じられていない場合、プログラムは例外なしで終了します。これが私のコードです:

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.

をusingブロック内に配置すると、が に変更されSqlConnectionない限り、アプリケーションがハングする原因にもなります。CommandBehavior.KeyInfoCommandBehavior.SchemaOnly

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 万行以上ありますが、スキーマ情報を取得しているだけなので、問題にはならないと思います。私の質問は、接続を閉じようとしているときにアプリケーションが動かなくなるのはなぜですか?

解決策:これは最適ではないかもしれませんが、うまくいきます。接続時に呼び出されるcommand.Cancel();直前にステートメントを挿入しました。Close

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

5 に答える 5

7

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

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を参照してください。

于 2012-04-19T01:52:52.683 に答える
0

SMO(SQL Server管理オブジェクト)を使用して、これを行う特定の方法があります

データベース内のテーブルのコレクションを取得してから、関心のあるテーブルのプロパティ(列、キー、および考えられるすべてのプロパティ)を読み取ることができます。

これは、SSMSがすべてのデータベースオブジェクトのプロパティを取得および設定するために使用するものです。

この参考文献を見てください:

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

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

于 2012-04-18T22:02:26.643 に答える
0

全体的に私には合っているように見えますが、少し最適化する必要があると思います。DataReader の回避に関する上記の提案に加えて、接続プールを使用することをお勧めします。ここから詳細を取得できます。

http://www.techrepublic.com/article/take-advantage-of-adonet-connection-pooling/6107854

于 2012-04-18T21:33:21.233 に答える
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);
    }
于 2012-04-19T00:47:37.217 に答える
0

これを試していただけますか?

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()); 
}

MSDN からのSET FMTONLY ON/OFFが有効なようです

于 2012-04-18T21:48:53.817 に答える