1

我执行一个调用 SP 的查询,该 SP 返回数据......但是当我用 DataAdapter 调用它时,我没有得到任何结果数据,如果改用 DataReader......然后我得到数据。数据库是 SQL Server,由于我无法更改的原因,代码正在使用 OleDb。

这两个调用返回不同的东西:

    String commandText = "Declare @return_value int;  exec dbo.copyTemplate ? , ? , ? , ? , ? ,  ? ,   ?, Null , 0 , @return_value;";

    Console.WriteLine("Data Adapter");
    using (OleDbConnection con = new OleDbConnection(connectionString))
    {
        using (OleDbDataAdapter da = new OleDbDataAdapter(commandText, con))
        using (DataTable table = new DataTable("table"))
        {
            da.SelectCommand.Parameters.AddWithValue("?",9).DbType = DbType.Int32;
            da.SelectCommand.Parameters.AddWithValue("?", "AAAAB").DbType = DbType.String;
            da.SelectCommand.Parameters.AddWithValue("?", 1).DbType = DbType.Int32;
            da.SelectCommand.Parameters.AddWithValue("?", 1).DbType = DbType.Int32;
            da.SelectCommand.Parameters.AddWithValue("?", 2).DbType = DbType.Int32;
            da.SelectCommand.Parameters.AddWithValue("?", true).DbType = DbType.Boolean;
            da.SelectCommand.Parameters.AddWithValue("?", DateTime.Now.Date).DbType = DbType.DateTime;

            da.Fill(table);

            foreach (DataRow dr in table.Rows)
            {
                foreach (DataColumn dc in table.Columns)
                {
                    Console.Write(dr[dc].ToString());
                    Console.Write(" ");
                }
                Console.WriteLine();
            }
        }
    }
    Console.WriteLine("Data Reader");
    using (OleDbConnection con = new OleDbConnection(connectionString))
    {
        using (OleDbCommand cmd = new OleDbCommand(commandText, con))
        {
            cmd.Parameters.AddWithValue("?", 9).DbType = DbType.Int32;
            cmd.Parameters.AddWithValue("?", "AAAAC").DbType = DbType.String;
            cmd.Parameters.AddWithValue("?", 1).DbType = DbType.Int32;
            cmd.Parameters.AddWithValue("?", 1).DbType = DbType.Int32;
            cmd.Parameters.AddWithValue("?", 2).DbType = DbType.Int32;
            cmd.Parameters.AddWithValue("?", true).DbType = DbType.Boolean;
            cmd.Parameters.AddWithValue("?", DateTime.Now.Date).DbType = DbType.DateTime;

            con.Open();

            using (OleDbDataReader reader = cmd.ExecuteReader())
                while (reader.Read())
                {
                    for (int i = 0; i < reader.FieldCount; i++)
                    {
                        Console.Write(reader.GetValue(i) ?? "null");
                        Console.Write(" ");
                    }
                    Console.WriteLine();
                }
        }
    }

    Console.ReadKey(true);

此代码返回:

Data Adapter
Data Reader
1057

我可以调用此代码数百次,我总是在数据读取器中得到一个值,而在数据适配器中没有任何值,我可以在第二个参数中拥有任何内容,它不会改变 SP 的结果中的任何内容。我可以在两个调用之间交换参数值,或者改变顺序……结果还是一样的:(

我不明白为什么会这样。

有人知道可能是什么问题吗?

干杯。

更新:如果我填充 DataSet 而不是 DataTable 我得到结果:

    Console.WriteLine("Data Adapter with DataSet");
    using (OleDbConnection con = new OleDbConnection(connectionString))
    {
        using (OleDbDataAdapter da = new OleDbDataAdapter(commandText, con))
        using (DataSet ds = new DataSet("table"))
        {
            da.SelectCommand.Parameters.AddWithValue("?",9).DbType = DbType.Int32;
            da.SelectCommand.Parameters.AddWithValue("?", "AAAAB").DbType = DbType.String;
            da.SelectCommand.Parameters.AddWithValue("?", 1).DbType = DbType.Int32;
            da.SelectCommand.Parameters.AddWithValue("?", 1).DbType = DbType.Int32;
            da.SelectCommand.Parameters.AddWithValue("?", 2).DbType = DbType.Int32;
            da.SelectCommand.Parameters.AddWithValue("?", true).DbType = DbType.Boolean;
            da.SelectCommand.Parameters.AddWithValue("?", DateTime.Now.Date).DbType = DbType.DateTime;

            da.Fill(ds);

            foreach (DataTable table in ds.Tables)
                foreach (DataRow dr in table.Rows)
                {
                    foreach (DataColumn dc in table.Columns)
                    {
                        Console.Write(dr[dc].ToString());
                        Console.Write(" ");
                    }
                    Console.WriteLine();
                }
        }
    }

但是 DataSet 只包含一个表,所以我仍然不明白为什么 DataAdapter.Fill(DataTable) 不起作用。

4

1 回答 1

2

问题是存储过程(正如@leppie 指出的那样)返回几个结果集,第一个是空的,第二个包含实际结果。

DataAdapter.Fill(DataTable) 仅获取第一个结果集并将其放在 DataTable 上,由于该结果为空,因此您将获得一个空的 DataTable。您无法获得“null”,因为 DataTable 已经创建,适配器只是填充 DataTable。

DataReader 遍历所有结果集,因此您在这里得到了结果,但这样使用它是错误的。因为第一个结果集为空,所以现在没有问题,但如果存储过程或即席查询返回多个结果集,您可能会得到两个或多个不同的表,设置不同的列并将所有内容都放在一个 DataTable 中。

DataAdapter.Fill(DataSet) 为每个结果集获取一个 DataTable,因为第一个为空,而第二个中只有数据,您将获得一个只有一个 DataTable 的 DataSet。

解决这个问题的正确和无痛的方法是修复存储过程并只返回一个结果集,可能有一些东西在 SP 中返回一个空变量或类似的东西。如果要支持多个结果集,则必须使用 DataAdapter.Fill(DataSet) 并处理填充的 DataSet 中可能存在多个 DataTable 的想法。

http://social.msdn.microsoft.com/Forums/en-US/adodotnetdataproviders/thread/8fdbaa2d-1f1e-461f-8505-b80ea0c415f2

于 2010-10-14T14:51:37.423 回答