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 行を返します。新しく作成された ID をインデックスにまだ追加していないため、select はそれを見つけることができないため、すぐに 0 行を返すとしか思えません。

他の誰かが似たようなことに遭遇したことがありますか? もしそうなら、どのように対処しましたか?

DD

4

2 に答える 2

4

警告: あなたのコードはマルチユーザー環境で欠陥があります. 2 人のユーザーが同時にクエリを実行し、同じ ID を取得する可能性があります。列に主キーまたは候補キーがある場合、そのうちの 1 つが INSERT で失敗します。これは、キー フィールドのベスト プラクティスです。

ID を自動インクリメントの整数フィールドにするか (私はそれらのファンではありません)、キーのテーブルを作成することをお勧めします。テーブル内の各レコードは、割り当てられたキーを取得するテーブル用です。私はこれに似た構造を使用します:

       構造: countergenerator.dbf
       データベース名: conferencereg.dbc
     長いテーブル名: countergenerator
   レコード数: 0
        最終更新日: 2008 年 11 月 8 日
メモファイルのブロックサイズ:64
           コードページ: 1252
          テーブル タイプ: Visual FoxPro テーブル

フィールド名 タイプ サイズ Null 次のステップ デフォルト  
-------------------------------------------------- -------------------------------------------------- ------------
    1 ccountergenerator_pk 文字 36 N guid(36)  
    2 ckey 文字 (バイナリ) 50 Y                          
    3 ivalue 整数 4 Y                          
    4mメモメモ4Y「自動作成」  
    5 cuserid キャラクター 30 Y                        
    6 tupdated DateTime 8 Y DATETIME()  

索引タグ:
1.タグ名:PRIMARY
 - タイプ: プライマリ
 - キー式: ccountergenerator_pk
 - フィルター: (なし)
 - 順序: 昇順
 - 丁合順:機械

2.タグ名:CKEY
 - タイプ: レギュラー
 - キー表現: 下(ckey)
 - フィルター: (なし)
 - 順序: 昇順
 - 丁合順:機械

DBC (または別のプログラム) のストアド プロシージャのコードは次のとおりです。

FUNCTION NextCounter(tcAlias)

LOCAL lcAlias、; lnNextValue、; lnOldReprocess, ; 旧エリア

lnOldArea = SELECT()

IF PARAMETERS() < 1 lcAlias = エイリアス()

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('再処理')

*-- ユーザーが Esc を押すまでロックする SET REPROCESS TO AUTOMATIC

IF !USED("countergenerator") USE EventManagement!countergenerator IN 0 SHARED ALIAS 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() GATHER MEMVAR MEMO

IF RLOCK() lnNextValue = countergenerator.iValue countergenerator.iValue WITH countergenerator.iValue + 1 UNLOCK ENDIF ENDIF を置換

SELECT (lnOldArea) 再処理を lnOldReprocess に設定

RETURN lnNextValue ENDFUNC

RLOCK() は、レコードの競合がないことを保証し、プロセスのボトルネックにならないほど高速です。これは、現在取っているアプローチよりもはるかに安全です。

リック・シューマー
VFP MVP

于 2009-07-11T00:21:28.187 に答える
0

VFP はその作業領域をFLUSHする必要があります。

于 2009-07-10T16:04:43.597 に答える