:: Visual Foxpro, Foxpro for DOS
Помогите с CursorAdapter
lemenev
Автор

Сообщений: 113
Дата регистрации: 23.06.2022
Пытаюсь «взнуздать» CursorAdapter. Как я понимаю, его возможности двунаправлены: из исходных таблиц/курсоров в результирующий курсор и из результирующего курсора в исходные таблицы/курсоры. Первая часть у меня получается, а вторая - нет.
Пожалуйста, подскажите, что не так в моём простом примере.

CLOSE TABLES
SET MULTILOCKS ON
IF .f.
CREATE CURSOR Sbit (Kod I Autoinc, Tovar C(50), Cena Y, Kolvo N(9,2))
ELSE
IF NOT FILE('Sbit.dbf')
CREATE TABLE Sbit (Kod I Autoinc, Tovar C(50), Cena Y, Kolvo N(9,2))
ENDIF
IF NOT USED('Sbit')
USE Sbit
ENDIF
ENDIF
=CURSORSETPROP('Buffering', 5, 'Sbit' ) && оптимистическая буферизация для таблицы
loCAD = CREATEOBJECT('CursorAdapter')
IF VARTYPE(loCAD)='O'
WITH loCAD
.Alias = 'temp' && результат команды SELECT
.AllowDelete = .T.
.AllowInsert = .T.
.AllowUpdate = .T.
.DataSourceType = "Native" && тип исходных данных
* .DataSource = && для Native не определяется
.BufferModeOverride = 5 && 5 - буферизация таблицы, 3 - буферизация строк
.SelectCmd = "SELECT Kod, Tovar, Cena, Kolvo, Cena*Kolvo AS Summa "+;
"FROM Sbit " && WHERE Kod = xKod"
* && структура результирующего курсора
.CursorSchema = "Kod I, Tovar C(50), Cena Y, Kolvo N(9,2), Summa Y"
.Tables = "Sbit" && список исходных таблиц
.InsertCmd = "INSERT INTO Sbit (Tovar, Cena, Kolvo) SELECT ALL Tovar, Cena, Kolvo FROM Temp "
.InsertCmdDataSourceType = ""
* .UpdateCmd =
.KeyFieldList = "Kod" && список ключевых полей
.UpdatableFieldList = "Tovar, Cena, Kolvo" && список обновляемых полей
* список обновляемых имен
.UpdateNameList ="Tovar Sbit.Tovar, Cena Sbit.Cena, Kolvo Sbit.Kolvo"
* .SendUpdates = .T. && посылать ли запрос на обновления
.WhereType = 3 && как используется секция параметров WHERE
* .DeleteCmd =
* .UseTransactions = .T. && использовать транзакции через ADO или ODBC
.ConflictCheckType = 3 && тип проверки конфликта
IF .CursorFill(.T.) && заполнить курсор данными
ELSE
AERROR(laErrors)
MESSAGEBOX(laErrors[2])
DISPLAY MEMORY LIKE laErrors
ENDIF
ENDWITH
ELSE
MESSAGEBOX('Ошибка подключения к базе!')
ENDIF
************************************************************************
INSERT INTO Temp (Tovar, Cena, Kolvo) VALUES ('Винт', 1, 1)
INSERT INTO Temp (Tovar, Cena, Kolvo) VALUES ('Гайка', 2, 2)
SELECT Temp
BROWSE TITLE "Temp" &&LAST
IF .F.
* Этот вариант работает
SCAN FOR !DELETED()
IF EMPTY(Kod)
INSERT INTO Sbit (Tovar, Cena, Kolvo) VALUES (Temp.Tovar, Temp.Cena, Temp.Kolvo)
ELSE
UPDATE Sbit SET Tovar=Temp.Tovar, Cena=Temp.Cena, Kolvo=Temp.Kolvo ;
WHERE Sbit.Kod=Temp.Kod AND Sbit.Tovar=Temp.Tovar
ENDIF
ENDSCAN
ENDIF
IF NOT TABLEUPDATE(1,.T.,'Sbit')
AERROR(laErrors)
MESSAGEBOX(laErrors[2])
ENDIF
SELECT Sbit
BROWSE TITLE "Sbit" &&LAST
Ratings: 0 negative/0 positive
Re: Помогите с CursorAdapter
PaulWist

Сообщений: 14619
Дата регистрации: 01.04.2004
* .SendUpdates = .T. && посылать ли запрос на обновления

Убрать коммент.


------------------
Есть многое на свете, друг Горацио...
Что и не снилось нашим мудрецам.
(В.Шекспир Гамлет)
Ratings: 0 negative/0 positive
Re: Помогите с CursorAdapter
dimag

Сообщений: 464
Откуда: Одинцово
Дата регистрации: 17.12.2002
Почитай журнал FoxTalk за 0309 mega.nz там про курсор адаптер есть статья


------------------
Глупость - это не отсутствие ума, это такой ум.
Ratings: 0 negative/0 positive
Re: Помогите с CursorAdapter
lemenev
Автор

Сообщений: 113
Дата регистрации: 23.06.2022
PaulWist
* .SendUpdates = .T. && посылать ли запрос на обновления
Убрать коммент.
К сожалению, это не помогло.
Из Help
Установка свойства SendUpdates применяется только к тем объектам CursorAdapter, которые имеют в качестве источников данных ODBC или ADO.
У меня .DataSourceType = "Native".

dimag
Почитай журнал FoxTalk за 0309 mega.nz там про курсор адаптер есть статья
В номере за март 2009 года нет статьи о CursorAdapter. Я просмотрел все выпуски за 2009 год. Нигде нет. Может быть другой год?
Ratings: 0 negative/0 positive
Re: Помогите с CursorAdapter
dimag

Сообщений: 464
Откуда: Одинцово
Дата регистрации: 17.12.2002
Вот нашел doughennig.com


------------------
Глупость - это не отсутствие ума, это такой ум.
Ratings: 0 negative/0 positive
Re: Помогите с CursorAdapter
Burn

Сообщений: 5644
Откуда: Днепр
Дата регистрации: 02.01.2002
Использовал такую структуру:

.InsertCmd = "INSERT INTO Sbit (Tovar, Cena, Kolvo) SELECT ?Temp.Tovar,?Temp. Cena,?Temp. Kolvo"

А впринципе если что выбираешь то и возвращаешь можно вполне обойтись без задания InsertCmd



Исправлено 1 раз(а). Последнее : Burn, 26.10.22 20:26
Ratings: 0 negative/0 positive
Re: Помогите с CursorAdapter
Владимир Максимов

Сообщений: 14100
Откуда: Москва
Дата регистрации: 02.09.2000
А можно уточнить, что именно "не получается"? Какие симптомы, как проверял?
Ratings: 0 negative/0 positive
Re: Помогите с CursorAdapter
lemenev
Автор

Сообщений: 113
Дата регистрации: 23.06.2022
Владимир Максимов
А можно уточнить, что именно "не получается"? Какие симптомы, как проверял?
В том примере, что я привёл: формирую CursorAdapter, получаю результирующий курсор Temp с помощью .CursorFill, добавляю данные в Temp, выполняю TABLEUPDATE. Смотрю исходную таблицу. Туда ничего не добавилось.
Видимо, что-то в параметрах CursorAdapter я задаю неправильно.
Ratings: 0 negative/0 positive
Re: Помогите с CursorAdapter
lemenev
Автор

Сообщений: 113
Дата регистрации: 23.06.2022
Burn
Использовал такую структуру:
.InsertCmd = "INSERT INTO Sbit (Tovar, Cena, Kolvo) SELECT ?Temp.Tovar,?Temp. Cena,?Temp. Kolvo"

А впринципе если что выбираешь то и возвращаешь можно вполне обойтись без задания InsertCmd
К сожалению, твой совет не помог. Что с заданием InsertCmd, что без него - не работает.
А что это за синтаксис с вопросительными знаками? Это Fox? Где про такое можно почитать?
Ratings: 0 negative/0 positive
Re: Помогите с CursorAdapter
Владимир Максимов

Сообщений: 14100
Откуда: Москва
Дата регистрации: 02.09.2000
Sbit - исходная таблица
Temp - курсор, в котором происходят изменения данных

CursorAdapter - это "обертка", которая отслеживает изменения в Temp. Поскольку Вы установили 5 режим буферизации, то событие, по которым изменения из таблицы Temp надо будет перенести в таблицу Sbit - это TableUpdate().

Но! Сброс буфера надо делать на таблице Temp. Ведь именно факт изменения в этой таблице отслеживает CursorAdapter

* Изменяем содержимое Temp
(...)
* Сброс буфера в Temp
IF NOT TABLEUPDATE(1,.T.,'Temp')
AERROR(laErrors)
MESSAGEBOX(laErrors[2])
ELSE
* Изменения попадут в буфер таблицы Sbit
* Поэтому понадобиться еще сделать сброс буфера в Sbit
IF NOT TABLEUPDATE(1,.T.,'Sbit')
AERROR(laErrors)
MESSAGEBOX(laErrors[2])
ENDIF
ENDIF
* Смотрим результат
SELECT Sbit
BROWSE TITLE "Sbit"
Ratings: 0 negative/1 positive
Re: Помогите с CursorAdapter
Владимир Максимов

Сообщений: 14100
Откуда: Москва
Дата регистрации: 02.09.2000
lemenev
А что это за синтаксис с вопросительными знаками? Это Fox? Где про такое можно почитать?

Да. Это синтаксис FoxPro. Это пришло из параметризированных View

Как создать параметрические представления

В оригинальной справке по Visual FoxPro это статья "How to: Create Parameterized Views"

Хотя отдельно для CursorAdapter такого не прописали

То, что идет после вопросительного знака - интерпретируется как "параметр" (константа). Там можно указать и имя переменной памяти. Надо будет только следить, чтобы эта переменная существовала на момент обращения к ней

Т.е. прежде, чем выполнить указанную команду FoxPro сделает "макроподстановку". Вместо параметра подставит его значение. Константу
Ratings: 0 negative/0 positive
Re: Помогите с CursorAdapter
ssa

Сообщений: 13008
Откуда: Москва
Дата регистрации: 23.03.2005
Владимир Максимов
Т.е. прежде, чем выполнить указанную команду FoxPro сделает "макроподстановку". Вместо параметра подставит его значение. Константу
Если точнее, то вставит результат вычисления выражения. Например:
where vendita.id_operatore=?.id_adt and vendita.dt_ufficio between ?Date(year(.txtData)-3, 1, 1) And ?Date(year(.txtdata)+1, 1, 1) and merce.promozione=1


------------------
Лень - это неосознанная мудрость.
Ratings: 0 negative/0 positive
Re: Помогите с CursorAdapter
of63

Сообщений: 25256
Откуда: Н.Новгород
Дата регистрации: 13.02.2008
() почему разрабы-фоксисты не сделали символ макроподстановки (?) внутри выражений SELECT, а символ (?) (символы на одной клавише русской размечены, может и на не русской) ?

Доб. ой, не правильно написал про клавишу "7"...

() Про помощь "с курсор-адаптером" , боюсь сбить адептов этого адаптера оболочки над SELEC-ом /(абстрактным, как пытались его сделать рарзрабы фокса). Проще понять, если ты умеешь сделать SQLSУЛУ...-конструкцию, то тебе не нужна оболочка "что-то там"

() Затупил, не стер для развлечения вашего )



Исправлено 2 раз(а). Последнее : of63, 27.10.22 21:29
Ratings: 2 negative/1 positive
Re: Помогите с CursorAdapter
lemenev
Автор

Сообщений: 113
Дата регистрации: 23.06.2022
of63
Про помощь "с курсор-адаптером" , боюсь сбить адептов этого адаптера оболочки над SELEC-ом /(абстрактным, как пытались его сделать рарзрабы фокса). Проще понять, если ты умеешь сделать SQLSУЛУ...-конструкцию, то тебе не нужна оболочка "что-то там"

Я умею составлять SELEC-запросы, а потом вручную вносить изменения отредактированного курсора в исходные таблицы. Меня подкупила именно автоматизация второй части процесса. То, что это универсальный механизм при изменении входных данных – для меня не актуально. Я не представляю, где могут быть задачи, в которых не определён источник входных данных, и нужно изначально закладываться и на базы/таблицы VFP, ODBC, ADO и XML.

Спасибо Владимиру Макмимову за объяснение работы механизмов работы буферов. Можно долго перечитывать Help, а просветление так и не наступает.

dimag подсказал хорошую статью Дуга Хеннига про CursorAdapter. На его сайте есть 3 статьи с примерами на эту тему. Они мне так понравились, что я их перевёл. Можно посмотреть в приложении. Честно говоря, 3 статью я не осилил. Это пока не мой уровень.

Программа заработала после того, как я выкинул всё лишнее и добавил совет от Владимира Макмимова. Странно, что потребовалось указать ключевое поле Kod в свойствах UpdatableFieldList и UpdateNameList, хотя оно не обновляется, а формируется автоматически. Без этого появляется сообзщение об ошибке: «Для таблицы обновления "Sbit" не заданы столбцы ключей. Воспользуйтесь свойством KeyFieldList курсора.» , хотя в оно указано в KeyFieldList.

Сейчас программа выглядит так:

CLOSE TABLES
SET MULTILOCKS ON
IF .T.
CREATE CURSOR Sbit (Kod I Autoinc, Tovar C(50), Cena Y, Kolvo N(9,2))
INDEX ON Kod TAG Kod
INSERT INTO Sbit (Tovar, Cena, Kolvo) VALUES ('Винт', 1, 1)
INSERT INTO Sbit (Tovar, Cena, Kolvo) VALUES ('Гайка', 2, 2)
ELSE
IF NOT FILE('Sbit.dbf')
CREATE TABLE Sbit (Kod I Autoinc, Tovar C(50), Cena Y, Kolvo N(9,2))
ENDIF
IF NOT USED('Sbit')
USE Sbit
ENDIF
ENDIF
=CURSORSETPROP('Buffering', 5, 'Sbit' ) && оптимистическая буферизация для таблицы
loCAD = CREATEOBJECT('CursorAdapter')
IF VARTYPE(loCAD)='O'
WITH loCAD
.Alias = "temp" && результат команды SELECT
.DataSourceType = "Native" && тип исходных данных
.SelectCmd = "SELECT Kod, Tovar, Cena, Kolvo, Cena*Kolvo AS Summa "+;
"FROM Sbit " && WHERE Kod = xKod"
* структура результирующего курсора
.CursorSchema = "Kod I, Tovar C(50), Cena Y, Kolvo N(9,2), Summa Y"
.KeyFieldList = "Kod" && список ключевых полей
.Tables = "Sbit" && список исходных таблиц
.UpdatableFieldList = "Kod, Tovar, Cena, Kolvo" && список обновляемых полей
* список обновляемых имен
.UpdateNameList ="Kod Sbit.Kod, Tovar Sbit.Tovar, Cena Sbit.Cena, Kolvo Sbit.Kolvo"
* заполним курсор данными
IF .CursorFill(.T.) && T - используем структуру курсора
ELSE
AERROR(laErrors)
MESSAGEBOX(laErrors[2])
DISPLAY MEMORY LIKE laErrors
ENDIF
ENDWITH
ELSE
MESSAGEBOX('Ошибка подключения к базе!')
ENDIF
************************************************************************
SELECT Temp
* Изменяем содержимое Temp
BROWSE TITLE "Temp" &&LAST
* Сброс буфера в Temp
IF NOT TABLEUPDATE(1,.T.,'Temp')
AERROR(laErrors)
MESSAGEBOX(laErrors[2])
ELSE
* Изменения попадут в буфер таблицы Sbit
* Поэтому понадобится ещё сделать сброс буфера в Sbit
IF NOT TABLEUPDATE(1,.T.,'Sbit')
AERROR(laErrors)
MESSAGEBOX(laErrors[2])
ENDIF
ENDIF
SELECT Sbit
BROWSE TITLE "Sbit" &&LAST
Ratings: 0 negative/4 positive
Re: Помогите с CursorAdapter
Taran

Сообщений: 13625
Откуда: Красноярск
Дата регистрации: 16.01.2008
Вот молодец человек.
И результатами поделился и статьями по теме.
Не часто такое у вопрошающих бывает.
Ratings: 0 negative/0 positive
Re: Помогите с CursorAdapter
Burn

Сообщений: 5644
Откуда: Днепр
Дата регистрации: 02.01.2002
Потеряли Kod в списках обновляемых полей?
Ratings: 0 negative/0 positive
Re: Помогите с CursorAdapter
lemenev
Автор

Сообщений: 113
Дата регистрации: 23.06.2022
Burn
Потеряли Kod в списках обновляемых полей?
Нет, не потерял, а думал, что его не нужно указывать, ведь у него свойство Autoinc. Оказалось, что указывать обязательно.

Кажется, я рано радовался. Если я добавляю записи в курсор, а затем помечаю их как удалённые, то они добавляются в исходную таблицу как неудалённые.
[attachment 36424 Q1.png]

[attachment 36425 Q2.png]

Как это исправить?
Ratings: 0 negative/0 positive
Re: Помогите с CursorAdapter
Burn

Сообщений: 5644
Откуда: Днепр
Дата регистрации: 02.01.2002
Делать Tableupdate() после удаления ?
Я просто с Naitiv не работал
Ratings: 0 negative/0 positive
Re: Помогите с CursorAdapter
lemenev
Автор

Сообщений: 113
Дата регистрации: 23.06.2022
Burn
Делать Tableupdate() после удаления ?
Я в browse делаю все изменения (добавления, исправления, удаления), а затем выполняю Tableupdate(). Старые записи из исходной таблицы правильно помечаются как удалённые, а новые - нет.
Ratings: 0 negative/0 positive
Re: Помогите с CursorAdapter
Владимир Максимов

Сообщений: 14100
Откуда: Москва
Дата регистрации: 02.09.2000
Физически, пометка на удаление - это заполнение определенного байта. Можно сказать, что это некое служебное поле таблицы. Но установить это значение можно, разумеется, только у существующей записи. А если запись новая, то и установить этот признак некуда. Т.е. теоретически, для подобных ситуаций надо было бы давать 2 команды подряд. Сначала Insert, чтобы создать запись, а потом Delete, чтобы установить метку на удаление

Но сама по себе ситуация не вполне обычная. Создать запись чтобы тут же ее удалить. Вероятно по этой причине такая ситуация в штатном механизме обновления не была предусмотрена. Такие случаи надо обрабатывать "вручную"
Ratings: 0 negative/0 positive


Извините, только зарегистрированные пользователи могут оставлять сообщения в этом форуме.

On-line: 8 (Гостей: 8)

© 2000-2024 Fox Club 
Яндекс.Метрика