1.CRecordset(不是派生类)是不是只能用forwardOnly方式打开?我试了其他几种都不行。如果那样的话,做虚拟列表的时候,SetAbsolutePosition就不能用了。是不是做虚拟列表的时候,只能用派生类?2数据集中的数据什么时候读到内存中?是Open的时候还是MoveNext的时候?
我曾经在MoveNext的时候,到1万多条的时候,出现内存不足。是不是MoveNext的时候才放到内存中?如果用SetAbsolutePosition(10000),那么前面的记录有没有放到内存中?

解决方案 »

  1.   

    我也试了一下,发现CRecordset(不是派生类)只能用forwardOnly方式打开。我一般不用SetAbsolutePosition,因为本身sql server就不支持行号的,我是用key键来定位的,这样做更可靠一些,特别是在多个用户在同时对数据库进行操作时,行数随时都有可能被别的用户改变,我不知道系统是怎样处理这个行号,我总觉得不可靠或是效率低。
    数据库中的数据不会一次读到内在中的,因为:
    1、如果数据库中有几十亿或上百亿的数据怎么一次性读到内存中?这需要多大的内存和时间?
    2、MoveNext()是调用ODBC API的SQLExtendedFetcht和SQLFetch来实现的,这些函数只是读入一些特定行的。这个可以参考MSDN。
      

  2.   

    同意楼上,我也遇到同样问题.试验后证明只能forwardOnly方式打开,因为对于OPEN函数来说,其他几种方式都需要用派生类绑定到具体的表,这样才能重载DoFieldExchange().该函数实现OPEN时数据交换.至于为什么forwardOnly方式可以,我认为他没有调用DoFieldExchange().我对CRecordset的读取数据,默认情况下好像是每次只保留了一行的记录,不知道是不是这样?
    如果这样,不应有内存问题.
      

  3.   

    1.CRecordset(不是派生类)是什么意思?
    2.应该不是一次性读入的,默认读入多少行SQL SERVER应该自己知道。
      

  4.   

    用 CRecordset 通过ODBC 查询  ORACLE 时,查询的语句能不能用子查询呢?table test
    {  seq_no    varchar2(20);
       count_no  varchar2(20);
       cp_flag varchar2(2);
       count   int;
       name    varchar2(200);
    }
    查询语句能否实现:
    如 select * from test t1
      where cp_flag='1' 
        and exists(select * from test t2 
                    where t2.count_no = t1.count_no 
                      and cp_flag not in ('2','3');)
      

  5.   

    请问如果实现呢?
    假如 只派生一个CRecordset 如何能够实现呢?现有一个方法 
    1.通过建一个view 。CRecordset 从view 中取数。想使用ODBC中的方法。thx.
    用 CRecordset 通过ODBC 查询  ORACLE 时,查询的语句能不能用子查询呢?table test
    {  seq_no    varchar2(20);
       count_no  varchar2(20);
       cp_flag varchar2(2);
       count   int;
       name    varchar2(200);
    }
    查询语句能否实现:
    如 select * from test t1
      where cp_flag='1' 
        and exists(select * from test t2 
                    where t2.count_no = t1.count_no 
                      and cp_flag not in ('2','3');)
      

  6.   

    to  GEORGEAJ(驹仔):请不要在别人的帖子内提问。你的问题可以实现。
    1。使用派生类,对应的表选test t1,选中你所要用到的所有字段。
       CMyRecordset rs;
       rs.Open("select ....");
    2.直接使用CRecordset打开,用GetFieldValue取得每个字段的值。请不要在这里提问题了。另开贴子吧。
      

  7.   

    我今天试了,又出现“常见错误:不能写入文件缓冲区"我用CRecordset的派生类,用snapshot方式打开。我直接用
    str="select * from table1";
    m_set.Open(CRecordset::snapshot,str);
    while (!m_set.IsEOF())
    m_set.MoveNext();其他操作都没做。然后就内存不足了(有兴趣的可以试一下,找个几万条的表,用forwardOnly以外的方式打开)。我打开一个有8万条记录的表,花了很长时间,看到c盘下的空间一直减小。临时文件增大到500M,最后,硬盘没有空间当缓冲区了,就发生错误了。
    如果用snapshot改成forwardOnly,就不会发生错误。数据库Oracle.不知道为什么,我只能用snapshot和forwardOnly两种方式打开。可能是数据库的关系。我认为Move的时候,是有分配内存空间的。只有forwardOnly方式没有。主要是forwardOnly没有调用DoFieldExchange().
      

  8.   

    MoveNext()是调用Move()函数。Move中用到FetchData()函数,FetchData()中用来ODBC API的SQLExtendedFetcht和SQLFetch来实现的,这些函数只是读入一些特定行的。但是DoFieldExchange()中RFX_Text分配内存了。
      

  9.   

    如果你是用派生类的话,想用CRecordset::dynaset和CRecordset::dynamic 要数据库支持的。我用forwardOnly一次性读过8万条,有26个field包括放在一个控件中显示,1分左右。如果用CRecordset::dynamic 会慢很多,而且如楼上所说,要写一个临时文件。所以对于大量的记录我只用forwardOnly
      

  10.   

    不知道临时文件是怎么存储的。不过即使几万条记录,几百M也太夸张了。to small_wei:用forwardOnly怎么对数据进行定位?我在打开大数据量表的时候,用了虚拟列表。Oracle支持行数。但是像我上面说的那样,一开始打开,只是Move到前几十条记录,但是我如果把滚动条拉到最底下,前面读出的内存没有释放,就内存不足了。
    void CDlgNumChg::OnGetdispinfoList(NMHDR* pNMHDR, LRESULT* pResult) 
    {
    LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR;
    // TODO: Add your control notification handler code here
    short index = pDispInfo->item.iItem; 
    short subItem = pDispInfo->item.iSubItem; 
    if(pDispInfo->item.mask & LVIF_TEXT) 

    try 

    m_set.SetAbsolutePosition(index+1);//Set the file to desired index 
    CString szValues;
    if(subItem)  
    m_set.GetFieldValue(subItem, szValues); 
    else 
    m_set.GetFieldValue(short(0), szValues); 
    lstrcpyn(pDispInfo->item.pszText, szValues, pDispInfo->item.cchTextMax);//set item text } 
    catch(CDBException* e) 

    e->ReportError();
    e->Delete();
    return;  

    }
    *pResult = 0;
    }
      

  11.   

    如果用forwardOnly,
    m_set.SetAbsolutePosition(index+1);//Set the file to desired index 
    是不是该改为m_set.Requey();
    for (int i=0;i<index;i++)
    m_set.MoveNext();//这样如果是排在后面的记录,不是慢死了?或CString str;
    str="select ... from (select rownum,... from table where..) where rownum = index);
    m_set.strFilter = str;
    m_set.Requery();
    ...还没试,不知可行否?
      

  12.   

    不好意思,我没有用过Oracle,也没有用过SetAbsolutePosition。你在前面说过内存不足,我想不会有这种问题吧?因为内存是由系统管理的,当物理内存不足时,系统会使用虚拟内存的,应该不会出现内存不足的问题,只是速度慢而已。除非你连存储拟内存的硬盘空间都有不够了,才会有内存不足的问题。
    如果你在数据表中有行数的话,我还是比较喜欢自已处理行号问题,如你的:
    或CString str;
    str="select ... from (select rownum,... from table where..) where rownum = index);
    m_set.strFilter = str;
    m_set.Requery();
    ...
      

  13.   

    谢谢small wei.我说的内存不足,就是因为数据集生成临时文件,用了几百M内存,造成虚拟内存不足。硬盘C盘的空间都没有了。