2010-12-03 8 views
3

SqlDataReaderを使用してC#でクエリを実行しようとしていますが、データベースからエラーメッセージ "" "となります。SQLDataReaderを使用してC#でSQL Serverのクエリを実行する際に問題が発生する

私のSQLクエリで何が問題なのかよくわかりません。私はそれをSQL Server Management Studioで完璧に実行できます。

try 
{ 
    SqlConnection thisConnection = new SqlConnection(); 
    thisConnection.Open(); 
    SqlCommand thisCommand = thisConnection.CreateCommand(); 
    thisCommand.CommandText = "SELECT" 
       +"db.name DBName," 
       +"tl.request_session_id," 
       +"wt.blocking_session_id," 
       +"OBJECT_NAME(p.OBJECT_ID) BlockedObjectName," 
       +"tl.resource_type," 
       +"h1.TEXT AS RequestingText," 
       +"h2.TEXT AS BlockingText," 
       +"tl.request_mode" 
       +"FROM sys.dm_tran_locks AS tl" 
       +"INNER JOIN sys.databases db ON db.database_id = tl.resource_database_id" 
       +"INNER JOIN sys.dm_os_waiting_tasks AS wt ON tl.lock_owner_address = wt.resource_address" 
       +"INNER JOIN sys.partitions AS p ON p.hobt_id = tl.resource_associated_entity_id" 
       +"INNER JOIN sys.dm_exec_connections ec1 ON ec1.session_id = tl.request_session_id" 
       +"INNER JOIN sys.dm_exec_connections ec2 ON ec2.session_id = wt.blocking_session_id" 
       +"CROSS APPLY sys.dm_exec_sql_text(ec1.most_recent_sql_handle) AS h1" 
       +"CROSS APPLY sys.dm_exec_sql_text(ec2.most_recent_sql_handle) AS h2"; 

    SqlDataReader thisReader = thisCommand.ExecuteReader(); 
    while (thisReader.Read()) 
    { 
     Console.WriteLine("\t{0}\t{1}", thisReader["DBName"], thisReader["BlockedObjectName"]); 
    } 
    thisReader.Close(); 
    thisConnection.Close(); 
} 
catch (SqlException e) 
{ 
    Console.WriteLine(e.Message); 
} 
+1

推奨事項:あなたのIDisposable 'SqlConnection'、' SqlCommand'と 'SqlDataReader'を適切な処分を確実にするために' using(....){...} 'ブロックに入れてください。できるだけ早く 'ExecuteReader'の直前にあなたの接続を開いてください。 –

+0

SQLクエリで構文エラーを修正しました。 thisReader.Read()が実行された後、 "Enumeration yields no result"エラーが表示されるようになりました。なぜそれが –

答えて

15

あなたが連結されている線の一部の末尾にスペースが必要になります。たとえば

  +"tl.request_mode" 
      +"FROM sys.dm_tran_locks AS tl" 

はへ

...tl.request_modeFROM sys.dm_tran_locks AS tl... 

変更してSQLを作成します。

  +"tl.request_mode " 
      +"FROM sys.dm_tran_locks AS tl" 

同じ問題がある他の行もいくつかあります。

これは、コードを貼り付けるだけでなく、引用符と+記号を編集する代わりに、動的に構築されたSQL文字列をテストするときに連結文字列を実際に印刷することが重要な理由の良い例です。

+2

であるのか分からず、連結された文字列を使用する場合は、StringBuilderを使用してください。 – Brian

+3

@Brian - この場合、おそらく違いはありません。すべての文字列がこのようなリテラルである場合、コンパイラはMSILの1つの文字列でそれらを結合します。しかし、私は文字列の先頭に@を置いて、すべてのビジネスを失うことはとにかく読みやすいと思っています。 – JohnFx

+1

私は同じことをやろうとしていましたが、@メソッドの唯一の欠点は、タブがCIL内に残っていて、SELECT \ r \ n \ t \ t \ t \ t \ tdb.Name DBName、\ r \ n \ t \ t \ t \ t \ t \ t "'などリフレクタを使ってプロダクションコードを見るときに痛みを感じます(どのバージョンが配備されているかわからないとき) – Joshua

2

Johnが言いましたように、行が終わったらスペースが必要ですが、いくつか不足しています。

例として、あなたの最初のエラーが

SELECTdb.name DBName, 

ザッツ等しくなります最初の二行

thisCommand.CommandText = "SELECT" 
       +"db.name DBName," 

から来ている「近く不正な構文が 『』」から来ていますdb。がSELECTステートメントに追加されています。

1

JohnFxとkevchadderは、結果の文字列が適切な空白を持たないためにエラーが発生していることが正しいです。あなたはそれについて何ができるかについては - あなたが同じ形式で多かれ少なかれを維持するクエリをたい場合、あなたは-quoting @使用することができます。

thisCommand.CommandText = 
@"SELECT 
    db.name DBName, 
    tl.request_session_id, 
    wt.blocking_session_id, 
    OBJECT_NAME(p.OBJECT_ID) BlockedObjectName, 
    tl.resource_type, 
    h1.TEXT AS RequestingText, 
    h2.TEXT AS BlockingText, 
    tl.request_mode 
FROM sys.dm_tran_locks AS tl 
INNER JOIN sys.databases db ON db.database_id = tl.resource_database_id 
INNER JOIN sys.dm_os_waiting_tasks AS wt ON tl.lock_owner_address = wt.resource_address 
INNER JOIN sys.partitions AS p ON p.hobt_id = tl.resource_associated_entity_id 
INNER JOIN sys.dm_exec_connections ec1 ON ec1.session_id = tl.request_session_id 
INNER JOIN sys.dm_exec_connections ec2 ON ec2.session_id = wt.blocking_session_id 
CROSS APPLY sys.dm_exec_sql_text(ec1.most_recent_sql_handle) AS h1 
CROSS APPLY sys.dm_exec_sql_text(ec2.most_recent_sql_handle) AS h2 
"; 

SqlDataReader thisReader = thisCommand.ExecuteReader(); 

これはあなたのラインが終了し、他の空白そう尊重しますC#からSSMSに簡単にコピー&ペーストすることができる読みやすいクエリを得ることができます。ただし、空白のエラーはなく、連結なしで、すべてのStringBuilder.Appendステートメントがありません。

関連する問題