Reputation: 1768
I am converting an existing app from Sybase to SQL Server 2008. The app uses ODBC to connect to the database. 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:
{
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. However the DataTable is empty (no result set is returned).
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.
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. The code works as expected when using Sybase and when run in the 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.
Upvotes: 1
Views: 1497
Reputation: 8832
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):
1) in the beginning of the procedure after the begin
keyword add
set nocount on
2) Use the overload of Fill
method that takes DataSet
as parameter rather then the one that takes DataTable
.
MSDN states: The overload of Fill that takes DataTable as a parameter only obtains the first result.
When INSERT
is executed and NOCOUNT
is off, information on how many rows were affected by the statement gets returned. 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. 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.
Upvotes: 1