Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/264.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何知道何时停止填充OracleDataAdapter_C#_Oracle_Odp.net - Fatal编程技术网

C# 如何知道何时停止填充OracleDataAdapter

C# 如何知道何时停止填充OracleDataAdapter,c#,oracle,odp.net,C#,Oracle,Odp.net,我正在访问oracle的项目中使用OPD.NET dll 用户可以在文本框中键入任何SQL,然后对db执行该文本框。我一直在尝试使用OracleDataAdapter用resultset填充datatable,但我希望能够分阶段为大型select查询返回resultset 我的问题的一个例子是 如果一个select查询返回13行数据,下面的代码段将在第四次调用oda.Fill start row is 15之前无问题地执行,我猜想这是因为它正在调用一个已关闭或类似的读取器 然后,它将抛出Syst

我正在访问oracle的项目中使用OPD.NET dll

用户可以在文本框中键入任何SQL,然后对db执行该文本框。我一直在尝试使用OracleDataAdapter用resultset填充datatable,但我希望能够分阶段为大型select查询返回resultset

我的问题的一个例子是

如果一个select查询返回13行数据,下面的代码段将在第四次调用oda.Fill start row is 15之前无问题地执行,我猜想这是因为它正在调用一个已关闭或类似的读取器

然后,它将抛出System.InvalidOperationException,并显示消息-由于对象的当前状态,操作无效

如何确定命令最终将包含多少行,以避免遇到异常

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 foo, bar, COUNT(*) OVER () TheCount WHERE ...;

这样,整个查询的计数将随计数中的每一行一起返回,您可以将循环设置为相应终止。

有关Oracle中的分页,请参阅:

如果不运行单独的count*查询,就无法知道记录集计数。这是故意的。DataReader和DataAdapter是只读的,仅向前

如果效率是一个问题,即大型记录集,那么应该让数据库进行分页,而不是让OracleDataAdapter运行完整的查询。想象一下,如果谷歌在一个数据表中填写了每个用户搜索的所有1M+结果!!下面的文章解决了这一问题,尽管示例是在sql中:

我已经修改了下面的示例,允许对任何sql查询进行分页。调用过程负责跟踪用户的当前页面和页面大小。如果结果集小于请求的页面大小,则不再有页面

当然,从用户输入运行自定义sql是一个巨大的安全风险。但这不是眼前的问题

祝你好运-布雷特

DataTable 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;        
}

要获得对填充数据表循环的控制,您需要拥有该循环

然后使用OracleDataReader构建自己的函数来填充数据表

要获取列信息,可以使用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

嗨,Brett,这实际上只给了我一种填充结果集子集的不同方法,rowStart替换第一个参数,rowEnd替换第二个参数,即要检索多少条记录。我仍然需要做一个单独的查询来找到最大rowStart。谢谢,还有一个有趣的链接。听起来好像您正在尝试使用DataTable作为容器实现一个分页解决方案。我不清楚为什么这个分页解决方案不起作用。假设您希望一次翻页10条记录。然后,rowStart和rowEnd将类似于1、20、21、30、31、40等。当数据表返回为空或少于10行时,您就完成了。使用OracleDataAdapter的fill方法的好处是,它实际上不会使用requery=false重新查询db—它只是填充额外的数据。当数据表返回为空或少于10行时,使用该逻辑的问题在于,返回的最后一个数据表实际上可能包含最后一行,在这种情况下,仍然会引发异常。请参阅我的修订答案。祝你好运