0

所以主程序是C#。将新记录插入到 VFP 数据库表中。为记录生成下一个 ID 花费了太长时间

select max(id)+1 from table

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

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

select id form  table where id = *newlyReturnedID*

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

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

DD

4

2 回答 2

4

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

我的建议是让 ID 成为一个自动递增的整数字段(我不喜欢它们),或者更好的是,创建一个键表。表中的每条记录都用于分配键的表。我使用类似于这样的结构:

       结构:countergenerator.dbf
       数据库名称:conferencereg.dbc
     长表名称:countergenerator
   记录数:0
        最后更新:2008 年 11 月 8 日
备忘录文件块大小:64
           代码页:1252
          表类型:Visual FoxPro 表

字段名称 类型 大小 空 下一步 默认  
-------------------------------------------------- -------------------------------------------------- ------------
    1 ccountergenerator_pk 字符 36 N guid(36)  
    2 ckey 字符(二进制) 50 Y                          
    3 ivalue 整数 4 Y                          
    4 mnote 备忘录 4 Y “自动创建”  
    5 cuserid 字符 30 Y                        
    6 tupdated DateTime 8 Y DATETIME()  

索引标签:
1. 标签名称:PRIMARY
 - 类型:初级
 - 关键表达式:ccountergenerator_pk
 - 过滤器:(无)
 - 顺序:升序
 - 整理顺序:机器

2.标签名称:CKEY
 - 类型:常规
 - 关键表达式:lower(ckey)
 - 过滤器:(无)
 - 顺序:升序
 - 整理顺序:机器

现在 DBC(或另一个程序)中存储过程的代码是这样的:

功能 NextCounter(tcAlias)

本地 lcAlias, ; ln下一个值,; lnOldReprocess, ; 旧区

lnOldArea = 选择()

如果 PARAMETERS() < 1 lcAlias = ALIAS()

IF CURSORGETPROP("SOURCETYPE") = DB_SRCLOCALVIEW *-- 尝试获取基表 lcAlias = LOWER(CURSORGETPROP("TABLES")) lcAlias = SUBSTR(lcAlias, AT("!", lcAlias) + 1) ENDIF ELSE lcAlias = LOWER (tcAlias) ENDIF

lnOrderNumber = 0 lnOldReprocess = SET('REPROCESS')

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

IF !USED("countergenerator") 使用 EventManagement!countergenerator IN 0 共享别名 countergenerator ENDIF

选择反发电机

IF SEEK(LOWER(lcAlias), "countergenerator", "ckey") IF RLOCK() lnNextValue = countergenerator.iValue REPLACE countergenerator.iValue WITH countergenerator.iValue + 1 UNLOCK ENDIF ELSE * 使用起始值创建新记录。APPEND BLANK IN countergenerator SCATTER MEMVAR MEMO m.cKey = LOWER(lcAlias) m.iValue = 1 m.mNote = "由存储过程自动创建。" m.tUpdated = DATETIME() 收集 MEMVAR 备忘录

IF RLOCK() lnNextValue = countergenerator.iValue 用 countergenerator.iValue + 1 UNLOCK ENDIF ENDIF 替换 countergenerator.iValue

SELECT (lnOldArea) 将重新处理设置为 lnOldReprocess

返回 lnNextValue ENDFUNC

RLOCK() 确保没有记录争用,并且速度足够快,不会出现瓶颈。这比您当前采用的方法更安全。

里克·舒默
VFP MVP

于 2009-07-11T00:21:28.187 回答
0

VFP 需要刷新其工作区。

于 2009-07-10T16:04:43.597 回答