C# 使用SQLDataReader在C中执行SQL Server查询时出现问题

C# 使用SQLDataReader在C中执行SQL Server查询时出现问题,c#,.net,sql,sql-server,C#,.net,Sql,Sql Server,我试图使用SqlDataReader在C中执行查询,但从数据库收到一条错误消息,“.”附近的语法不正确 我不确定我的SQL查询出了什么问题。我可以在SQLServerManagementStudio中完美地执行它 try { SqlConnection thisConnection = new SqlConnection(); thisConnection.Open(); SqlCommand thisCommand = thisConnection.CreateCommand

我试图使用SqlDataReader在C中执行查询,但从数据库收到一条错误消息,“.”附近的语法不正确

我不确定我的SQL查询出了什么问题。我可以在SQLServerManagementStudio中完美地执行它

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

在要连接的某些行的末尾需要空格:

例如:

            +"tl.request_mode"
            +"FROM sys.dm_tran_locks AS tl"
将创建SQL

 ...tl.request_modeFROM sys.dm_tran_locks AS tl...
换成

            +"tl.request_mode " 
            +"FROM sys.dm_tran_locks AS tl"
还有一些其他线路也有同样的问题


这是一个很好的例子,说明了为什么在测试动态构建的SQL字符串时,实际打印连接的字符串非常重要,而不仅仅是粘贴代码和编辑引号和+符号。

正如John所提到的,由于缺少一些空格,所以在行尾需要空格

例如,您的初始错误来自前两行

thisCommand.CommandText = "SELECT" 
                +"db.name DBName," 
哪个相等

SELECTdb.name DBName,

这就是“.”附近的错误语法来自as db的原因。正在将添加到SELECT语句中。

JohnFx和kevchadders认为错误是由于生成的字符串没有适当的空格造成的。至于你能做些什么-如果你希望查询或多或少保持相同的格式,你可以使用@-引号:

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复制到SSM中,无需空格错误、无需连接,也无需所有StringBuilder.Append语句。

建议:使用IDisposable SqlConnection、SqlCommand和SqlDataReader。。。。{…}块,以确保妥善处置;尽可能晚地打开连接-就在ExecuteReader之前-而不是更早。我用SQL查询修复了语法错误。现在我得到一个枚举,在执行thisReader.Read之后,不会产生任何结果错误。我不知道为什么会这样,如果你要使用连接字符串,请使用StringBuilder@Brian-在这种情况下,可能不会有什么不同。如果所有字符串都是这样的文本,编译器将在MSIL中将它们组合成一个字符串。但是,我仍然认为在字符串的前面加上@并丢失所有+业务将更具可读性。我正要说同样的话,@方法的唯一缺点是如果在CIL中保留选项卡,则看起来像SELECT\r\n\t\t\t\tdb.Name DBName,\r\n\t\t\t\t\t等。当您不确定部署的是什么版本时,使用Reflector查看生产代码会带来麻烦。。。