Вставка VFP, обновление индекса - PullRequest
0 голосов
/ 10 июля 2009

Итак, основная программа на C #. Вставка новых записей в таблицу базы данных VFP. Генерация следующего идентификатора для записи через

заняла слишком много времени
select max(id)+1 from table

, поэтому я поместил этот код в DLL компиляции в VFP и вызываю этот COM-объект через C #.

COM-объект возвращает новый идентификатор примерно через 250 мс. Я тогда просто делаю обновление через OLEDB. У меня проблема в том, что после того, как COM-объект возвращает вновь вставленный идентификатор, я не могу сразу найти его из C # через OLEDB

select id form  table where id = *newlyReturnedID*

возвращает 0 строк назад. Если я буду ждать неизвестного периода времени, запрос вернет 1 строку. Я могу только предположить, что он сразу возвращает 0 строк, потому что он еще не добавил вновь созданный идентификатор в индекс, и, следовательно, селектор не может его найти.

Кто-нибудь еще сталкивался с чем-то подобным? Если да, то как ты справился с этим?

DD

Ответы [ 2 ]

4 голосов
/ 11 июля 2009

Предупреждение: ваш код имеет недостатки в многопользовательской среде. Два человека могут выполнить запрос одновременно и получить один и тот же идентификатор. Один из них завершится с ошибкой INSERT, если у столбца есть первичный ключ или ключ-кандидат, что рекомендуется для ключевых полей.

Я рекомендую, чтобы идентификатор представлял собой целочисленное поле с автоинкрементом (я не фанат этого), или, что еще лучше, создайте таблицу ключей. Каждая запись в таблице предназначена для таблицы, которой назначены ключи. Я использую структуру, подобную этой:

       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 () </p>

IF CURSORGETPROP ("SOURCETYPE") = DB_SRCLOCALVIEW * - Попытка получить базовую таблицу lcAlias ​​= LOWER (CURSORGETPROP ("TABLES")) lcAlias ​​= SUBSTR (lcAlias, AT ("!", lcAlias) + 1) ENDIF ELSE lcAlias ​​= НИЖНЯЯ (tcAlias) ENDIF

lnOrderNumber = 0 lnOldReprocess = SET ('REPROCESS')

* - Блокировка, пока пользователь не нажмет Esc УСТАНОВИТЬ РЕПРОЦЕСС В АВТОМАТИЧЕСКИЙ

ЕСЛИ! ИСПОЛЬЗУЕТСЯ («контргенератор») ИСПОЛЬЗУЙТЕ КОНТРОГЕНЕРАТОР EventManagement! В 0 ПРОГРЕССИРОВАННЫЙ АЛИАС ENDIF

ВЫБРАТЬ контргенератор

IF SEEK (LOWER (lcAlias), «контргенератор», «ключ») ЕСЛИ RLOCK () lnNextValue = countergenerator.iValue ЗАМЕНИТЕ countergenerator.iValue НА countergenerator.iValue + 1 ОТКРЫТЬ ENDIF ELSE * Создать новую запись с начальным значением. APPEND BLANK IN контргенератор СКАТЕР МЕМВАР МЕМО m.cKey = LOWER (lcAlias) m.iValue = 1 m.mNote = "Автоматически создается хранимой процедурой." m.tUpdated = DATETIME () MEMVAR MEMO

IF RLOCK () lnNextValue = countergenerator.iValue ЗАМЕНИТЕ countergenerator.iValue НА countergenerator.iValue + 1 ОТКРЫТЬ ENDIF ENDIF

SELECT (lnOldArea) УСТАНОВИТЬ РЕПРОЦЕСС ДЛЯ LnOldReprocess

RETURN lnNextValue EndFunc

RLOCK () гарантирует отсутствие конкуренции за записи и является достаточно быстрым, чтобы не допустить узкого места в процессе. Это намного безопаснее, чем тот подход, который вы сейчас используете.

Рик Шуммер
VFP MVP

0 голосов
/ 10 июля 2009

VFP должен FLUSH его рабочие области.

...