简体   繁体   English

使用ODBC返回SQL Server结果集时出错

[英]Error returning SQL Server result set using ODBC

I am converting an existing app from Sybase to SQL Server 2008. The app uses ODBC to connect to the database. 我将现有的应用程序从Sybase转换为SQL Server2008。该应用程序使用ODBC连接到数据库。 Simply changing the connection string has worked for most of the apps functionality but there is one bug that has me puzzled. 只需更改连接字符串即可实现大多数应用程序功能,但是有一个让我感到困惑的错误。 I have created a simple example that shows the bug. 我创建了一个显示错误的简单示例。

I have a stored procedure: 我有一个存储过程:

create procedure dbo.test_sel
as 
begin
  create table #cfg
  (
    Name  varchar(100) NULL,
    Dscr  varchar(50)  NULL
  )

  insert #cfg(Name, Dscr) 
  values('Config', 'Config description')

  select COUNT(*) as [Count] from #cfg

  return 0
end

and code that executes the stored procedure and loads the results into a DataTable: 和执行存储过程并将结果加载到DataTable中的代码:

{
    OdbcCommand cmd = new OdbcCommand("test_sel", new OdbcConnection("Driver={SQL Server};Server=xxx;Database=xxx;Uid=xxx;Pwd=xxx"));

    DataTable dt = new DataTable();

    OdbcDataAdapter da = new OdbcDataAdapter(cmd);

    using (cmd.Connection)
    {
        da.Fill(dt);
    }

    MessageBox.Show(dt.Rows.Count.ToString());
}

I would expect the message to show the value 1 and the DataTable to contain a single row. 我希望消息显示值1,并且DataTable包含一行。 However the DataTable is empty (no result set is returned). 但是,DataTable为空(不返回任何结果集)。

Now, if I comment out the insert statement in the stored procedure and rerun the code then I do get a result set returned containing one row, one column named count with a value of 0. 现在,如果我注释掉存储过程中的insert语句并重新运行代码,那么我确实得到了返回的结果集,其中包含一行,其中一列名为count,值为0。

I have tried many variants of the stored procedure, using a permanent table rather than temporary, for example but each time the same thing happens - having the insert stops the stored procedure from returning a result set. 我尝试使用永久表而不是临时表来尝试存储过程的许多变体,例如,但是每次发生相同的事情时-插入都会阻止存储过程返回结果集。

Changing the ODBC driver to SQL Server 2008 makes no difference. 将ODBC驱动程序更改为SQL Server 2008没什么区别。 The code works as expected when using Sybase and when run in the MS SQL Server Management Studio. 使用Sybase并在MS SQL Server Management Studio中运行时,代码可以按预期工作。

After a google search I tried the following code: 谷歌搜索后,我尝试了以下代码:

{
    SqlCommand cmd = new SqlCommand("test_sel", new SqlConnection("Server=xxx,5100;Database=xxx;User ID=xxx;Password=xxx"));

    DataTable dt = new DataTable();

    SqlDataAdapter da = new SqlDataAdapter(cmd);

    using (cmd.Connection)
    {
        da.Fill(dt);
    }

    MessageBox.Show(dt.Rows.Count.ToString());
}

Now this works but I would rather not make code changes for this if I can help it because the app needs to work on both databases. 现在可以正常工作,但是如果我可以帮助的话,我不想更改代码,因为该应用程序需要在两个数据库上都可以工作。

Can anyone suggest why the original code does not work? 谁能说出原始代码为何无效? It really seems like something that simple should work OK. 看起来好像很简单的事情就可以了。

There are 2 options you can use to make this work (to me this seems like bug since Fill for both OdbcDataAdapter and SqlDataAdapter should work equally): 您可以使用2个选项来完成这项工作(对我来说,这似乎是个错误,因为对于OdbcDataAdapterSqlDataAdapter Fill均应正常工作):

1) in the beginning of the procedure after the begin keyword add 1)在程序begin后,在begin关键字中添加

set nocount on

2) Use the overload of Fill method that takes DataSet as parameter rather then the one that takes DataTable . 2)使用以DataSet为参数的Fill方法的重载,而不是使用DataTable方法的重载。

MSDN states: The overload of Fill that takes DataTable as a parameter only obtains the first result . MSDN指出: 以DataTable作为参数的Fill的重载仅获得第一个结果

When INSERT is executed and NOCOUNT is off, information on how many rows were affected by the statement gets returned. INSERT并且关闭NOCOUNT时,将返回有关该语句影响了多少行的信息。 So when you have this option off, count of rows will be reported 2 times (you can check that in SSMS, 'Messages' window), once for INSERT, second time for SELECT. 因此,关闭此选项后,行数将报告两次(您可以在SSMS的“消息”窗口中检查),一次用于INSERT,第二次用于SELECT。 It seems that first row count (from INSERT) somehow gets interpreted as first result set, this row count refers to INSERT statement not SELECT so there are no rows to return. 似乎第一行计数(来自INSERT)以某种方式被解释为第一个结果集,该行计数是指INSERT语句而不是SELECT因此没有要返回的行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM