我正在访问oracle的项目中使用OPD.NET dll。
用户可以在文本框中输入任何SQL,然后对数据库执行该操作。我一直在尝试使用OracleDataAdapter用结果集填充数据表,但我希望能够分阶段返回结果集(对于大型选择查询)。
我的问题的一个例子是......
如果一个select查询返回13行数据,那么下面的代码片段会一直没有问题地执行,直到第四次调用oda.Fill(起始行是15,它不存在),我猜是因为它调用了一个已关闭或类似的读者。
然后它会抛出一个带有消息的System.InvalidOperationException - 由于对象的当前状态,Operation无效。
如何确定命令最终将包含多少行(以便我不会遇到异常)?
OracleDataAdapter oda = new OracleDataAdapter(oracleCommand);
oda.Requery = false;
var dts = new DataTable[] { dt };
DataTable dt = new DataTable();
oda.Fill(0, 5, dts);
var a = dts[0].Rows.Count;
oda.Fill(a, 5, dts);
var b = dts[0].Rows.Count;
oda.Fill(b, 5, dts);
var c = dts[0].Rows.Count;
oda.Fill(c, 5, dts);
var d = dts[0].Rows.Count;
注意:为简洁起见,我省略了连接和oracle命令对象。
编辑1: 我只是想我可以将用户输入的SQL包装在另一个查询中并执行它... SELECT COUNT(*)FROM(...这里的... intial query ...) 但这不是一个干净的解决方案,当然有一种方法我还没有见过吗?
提前致谢。
答案 0 :(得分:1)
有关Oracle中的分页,请参阅:http://www.oracle.com/technology/oramag/oracle/06-sep/o56asktom.html
如果不运行单独的count(*)查询,则无法知道记录集计数。这是设计的。 DataReader和DataAdapter是只进的,只读。
如果关注效率(即大记录集),则应让数据库执行分页,而不要求OracleDataAdapter运行完整查询。想象一下,如果Google为每个用户搜索填充了一个包含所有1M +结果的DataTable !!以下文章解决了这个问题,尽管示例在sql:
中http://www.asp.net/data-access/tutorials/efficiently-paging-through-large-amounts-of-data-cs
我修改了下面的示例以允许在任何sql查询上进行分页。调用过程负责跟踪用户的当前页面和页面大小。如果结果集小于请求的页面大小,则不再有页面。
当然,从用户输入运行自定义sql是一个巨大的安全风险。但这不是手头的问题。
祝你好运! --BrettDataTable GetReport(string sql, int pageIndex, int pageSize)
{
DataTable table = new DataTable();
int rowStart = pageIndex * pageSize + 1;
int rowEnd = (pageIndex + 1) * pageSize;
string qry = string.Format(
@"select *
from (select rownum ""ROWNUM"", a.*
from ({0}) a
where rownum <= :rowEnd)
where ""ROWNUM"" >= :rowStart
", sql);
try
{
using (OracleConnection conn = new OracleConnection(_connStr))
{
OracleCommand cmd = new OracleCommand(qry, conn);
cmd.Parameters.Add(":rowEnd", OracleDbType.Int32).Value = rowEnd;
cmd.Parameters.Add(":rowStart", OracleDbType.Int32).Value = rowStart;
cmd.CommandType = CommandType.Text;
conn.Open();
OracleDataAdapter oda = new OracleDataAdapter(cmd);
oda.Fill(table);
}
}
catch (Exception)
{
throw;
}
return table;
}
答案 1 :(得分:0)
您可以在查询中添加分析COUNT:
SELECT foo, bar, COUNT(*) OVER () TheCount WHERE ...;
这样,整个查询的计数与TheCount中的每一行一起返回,您可以将循环设置为相应地终止。
答案 2 :(得分:0)
要获得对Fill DataTable Loop的控制权,您需要拥有循环。
然后使用OracleDataReader构建自己的函数来填充DataTable。
要获取列信息,您可以使用dataReader.GetSchemaTable
填写表格:
MyTable.BeginLoadData
Dim Values(mySchema.rows.count-1)
Do while myReader.read
MyReader.GetValues(Values)
MyTable.Rows.add(Values)
'Include here your control over load Count
Loop
MyTable.EndLoadData