VFP插入,索引更新

时间:2009-07-10 15:51:55

标签: indexing oledb visual-foxpro

所以主程序在C#中。将新记录插入VFP数据库表。通过

生成记录的下一个ID需要很长时间
select max(id)+1 from table

,所以我将该代码放入VFP中的编译dll中,并通过C#调用该COM对象。

COM对象在大约250ms内返回新ID。然后,我只是通过OLEDB进行更新。我遇到的问题是,在COM对象返回新插入的ID之后,我无法通过OLEDB立即从C#中找到它

select id form  table where id = *newlyReturnedID*

返回0行。如果我等待一段未知时间,查询将返回1行。我只能假设它立即返回0行,因为它尚未将新的ID添加到索引中,因此select无法找到它。

有没有其他人遇到过类似的事情?如果是这样,你是如何处理它的?

DD

2 个答案:

答案 0 :(得分:4)

警告:您的代码在多用户环境中存在缺陷。两个人可以同时运行查询并获得相同的ID。如果列具有主键或候选键,则其中一个将在INSERT上失败,这是关键字段的最佳实践。

我的建议是让ID成为自动递增的整数字段(我不是它们的粉丝),或者甚至更好,创建一个键表。表中的每条记录都是针对获取密钥的表。我使用类似于此的结构:

       Structure for: countergenerator.dbf
       Database Name: conferencereg.dbc
     Long table name: countergenerator
   Number of records: 0
        Last updated: 11/08/2008
Memo file block size: 64
           Code Page: 1252
          Table Type: Visual FoxPro Table

Field  Name                  Type                 Size   Nulls       Next       Step  Default  
----------------------------------------------------------------------------------------------------------------
    1  ccountergenerator_pk  Character            36         N                        guid(36)  
    2  ckey                  Character (Binary)   50         Y                          
    3  ivalue                Integer               4         Y                          
    4  mnote                 Memo                  4         Y                        "Automatically created"  
    5  cuserid               Character            30         Y                        
    6  tupdated              DateTime              8         Y                        DATETIME()  

Index Tags: 
1. Tag Name: PRIMARY
 - Type: primary
 - Key Expression: ccountergenerator_pk
 - Filter: (nothing)
 - Order: ascending
 - Collate Sequence: machine

2. Tag Name: CKEY
 - Type: regular
 - Key Expression: lower(ckey)
 - Filter: (nothing)
 - Order: ascending
 - Collate Sequence: machine

现在DBC(或其他程序)中存储过程的代码是:

功能NextCounter(tcAlias)

LOCAL lcAlias ,;       lnNextValue ,;       lnOldReprocess ,;       lnOldArea

lnOldArea = SELECT()

如果参数()< 1    lcAlias = ALIAS()

如果CURSORGETPROP(“SOURCETYPE”)= DB_SRCLOCALVIEW       * - 尝试获取基表       lcAlias = LOWER(CURSORGETPROP(“TABLES”))       lcAlias = SUBSTR(lcAlias,AT(“!”,lcAlias)+ 1)    万一 其他    lcAlias = LOWER(tcAlias) ENDIF

lnOrderNumber = 0 lnOldReprocess = SET('REPROCESS')

* - 锁定直到用户按下Esc SET REPROCESS TO AUTOMATIC

IF!USED(“countergenerator”)    使用EventManagement!countergenerator IN 0 SHARED ALIAS countergenerator ENDIF

SELECT countergenerator

如果寻求(LOWER(lcAlias),“countergenerator”,“ckey”)    如果RLOCK()       lnNextValue = countergenerator.iValue       使用countergenerator.iValue + 1替换countergenerator.iValue       开锁    万一 其他    *使用起始值创建新记录。    APPEND BLANK IN countergenerator    SCATTER MEMVAR备忘录    m.cKey = LOWER(lcAlias)    m.iValue = 1    m.mNote =“由存储过程自动创建。”    m.tUpdated = DATETIME()    收集MEMVAR备忘录

如果RLOCK()       lnNextValue = countergenerator.iValue       使用countergenerator.iValue + 1替换countergenerator.iValue       开锁    万一 ENDIF

SELECT(lnOldArea) 设置对lnOldReprocess的重现

RETURN lnNextValue ENDFUNC

RLOCK()确保不存在对记录的争用,并且足够快以至于没有瓶颈过程。这比你目前采用的方法更安全。

Rick Schummer VFP MVP

答案 1 :(得分:0)

VFP需要FLUSH其工作区。