Вставка VFP, обновление индекса
-
12-09-2019 - |
Вопрос
Итак, основная программа написана на 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 строк, потому что ему еще предстоит добавить новоиспеченный идентификатор в индекс, и поэтому select не может его найти.
Кто-нибудь еще когда-нибудь сталкивался с чем-то подобным?Если да, то как вы с этим справились?
ДД
Решение
Предупреждение:ваш код имеет недостатки в многопользовательской среде.Два человека могли бы выполнить запрос одновременно и получить один и тот же идентификатор.Один из них завершится ошибкой при ВСТАВКЕ, если столбец имеет первичный или потенциальный ключ, что является наилучшей практикой для ключевых полей.
Моя рекомендация состоит в том, чтобы либо сделать 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)
МЕСТНЫЕ КАЛИИ, ;lnNextValue, ;Процесс lnOldReprocess, ;Область действия
lnOldArea = ВЫБРАТЬ()
IF ПАРАМЕТРЫ() < 1 lcAlias = ПСЕВДОНИМ()
IF CURSORGETPROP("SOURCETYPE") = DB_SRCLOCALVIEW *-- Попытка получить базовую таблицу lcAlias = НИЖНИЙ(CURSORGETPROP("ТАБЛИЦЫ")) lcAlias = НИЖНИЙ(lcAlias, AT("!", lcAlias) + 1) КОНЕЧНЫЙ ещё lcAlias = НИЖНИЙ (tcAlias) КОНЕЧНЫЙ
lnOrderNumber = 0 lnOldReprocess = УСТАНОВИТЬ ('ПОВТОРНО ОБРАБОТАТЬ')
*-- Блокировка до тех пор, пока пользователь не нажмет клавишу Esc УСТАНОВИТЕ АВТОМАТИЧЕСКИЙ РЕЖИМ ПОВТОРНОЙ ОБРАБОТКИ
IF !ИСПОЛЬЗУЕТСЯ("countergenerator") ИСПОЛЬЗУЙТЕ EventManagement!countergenerator В 0 С ОБЩИМ ПСЕВДОНИМОМ countergenerator ENDIF
ВЫБЕРИТЕ контргенератор
IF SEEK(НИЖНИЙ (lcAlias), "контргенератор", "ckey") IF RLOCK() lnNextValue = контргенератор.IValue ЗАМЕНИТЕ контргенератор.IValue На countergenerator.IValue + 1 РАЗБЛОКИРОВАТЬ ENDIF ещё * Создайте новую запись с начальным значением.ДОБАВИТЬ ПРОБЕЛ В countergenerator РАЗБРОС MEMVAR MEMO m.cKey = НИЖНИЙ (lcAlias) m.IValue = 1 m.mNote = "Автоматически создается хранимой процедурой". m.tUpdated = DATETIME() СОБЕРИТЕ MEMVAR MEMO
IF RLOCK() lnNextValue = счетчик-генератор.IValue ЗАМЕНИТЕ счетчик-генератор.IValue НА countergenerator.IValue + 1 РАЗБЛОКИРУЙТЕ КОНЕЦ КОНЕЦ
SELECT (lnOldArea) УСТАНОВИТЕ ДЛЯ ПАРАМЕТРА REPROCESS ЗНАЧЕНИЕ lnOldReprocess
ВОЗВРАЩАЕТ значение lnNextValue ENDFUNC
RLOCK() гарантирует отсутствие конкуренции за записи и работает достаточно быстро, чтобы не создавать узких мест в процессе.Это намного безопаснее, чем подход, который вы используете в настоящее время.
Рик Шуммер
VFP MVP
Другие советы
ВФП необходимо РУМЯНЕЦ его рабочие зоны.