DataAdapter 返回空行集,但 DataReader 返回数据
我执行一个调用 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) 不起作用。
I execute a query that calls a SP, that SP returns data... but when I call it with a DataAdapter I get no result data, if use a DataReader instead... then I get data. The database is SQL Server and the code is using OleDb for reasons I cannot change.
These two calls returns diferent things:
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);
This code returns:
Data Adapter
Data Reader
1057
I can call this code hundreds of times and I always get a value in Data Reader a nothing in Data Adapter, and I can have whatever in the second parameter, it doesn't change anything in the result of the SP. I could swap the parameter values between the two calls, or alter the order... and the result would be still the same :(
I don't understand why is this happening.
Has anybody any idea about what could be the problem?
Cheers.
UPDATE: If I fill a DataSet instead a DataTable I get the result:
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();
}
}
}
But the DataSet contains only one table, so I still don't understand why DataAdapter.Fill(DataTable) is not working.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
问题是存储过程(正如 @leppie 指出的那样)返回多个结果集,第一个是空的,第二个包含实际结果。
DataAdapter.Fill(DataTable) 仅获取第一个结果集并将其放在 DataTable 上,因为该结果为空,所以您会得到一个空的 DataTable。你不能得到“null”,因为数据表已经创建,适配器只是填充数据表。
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
The problem is that the store procedure is (as @leppie pointed out) returning several result sets, the first is empty and the second one contains the actual result.
DataAdapter.Fill(DataTable) gets only the first result set and put it on a DataTable, as that result is empty, you get an empty DataTable. You cannot get “null” because the DataTable is already created, the adapter just fills the DataTable.
DataReader goes through all result sets, for that reason you got the result here, but it is wrong use it like that. Because the first result set is null, there is no problem right now, but if the store procedure or ad hoc query returns several result sets, you could get two or more different tables, with different columns set and messing everything up in one DataTable.
DataAdapter.Fill(DataSet) gets a DataTable per result set, as the first one is null, and there is only data in the second, you get a DataSet with only one DataTable.
The correct and painless way to solve this, is fix the stored procedure and returns just one result set, probably there is something that is returning a empty variable or something like that in the SP. If you want to support several results sets, you will have to use DataAdapter.Fill(DataSet) and to cope with the idea that maybe there is more than one DataTable in the filled DataSet.
http://social.msdn.microsoft.com/Forums/en-US/adodotnetdataproviders/thread/8fdbaa2d-1f1e-461f-8505-b80ea0c415f2