Проблема с tableupdate

Mr.Fontaine
Дата: 08.08.2012 11:45:55
Существует процедура, в которой в зависимости от значения входного параметра nvar открываем удалённые вьюхи.
Затем эти вьюхи используются в вызываемой далее форме, но так как в итоге создаётся только одна вьюха, то во всех четырёх вариантах присваиваем создаваемой вьюхе один и тот же алиас. с ним мы будем работать в форме
DO CASE 
   CASE nvar=1
         SELECT 0
         USE database!v_fisrt_plan ALIAS v_workdata 
         DO FORM f_first_form
   CASE nvar=2
         SELECT 0
         USE database!v_first_fakt ALIAS v_workdata
         DO FORM f_first_form
   CASE nvar=3
         SELECT 0
         USE database!v_second_plan ALIAS v_workdata
         DO FORM f_second_form
   CASE nvar=4
         SELECT 0
         USE ocen1!v_second_fakt ALIAS v_workdata
         DO FORM f_second_form
ENDCASE

ПОля, указанные во вьюхе выводим на вызываемой форме.
понадобилось одно поле редактировать и сохранять в БД

создал кнопку на форме в метод Click которой записал код
  PARAMETERS lnValue, lcForm 
  sele v_workdata
  SCATTER memvar
  IF lcForm = 'f_first_form' then
    m.field1 = lnValue
  endif
  IF lcForm = 'f_second_form' then
    m.field2 = lnValue
  endif
  SELECT v_workdata
  GATHER memvar
  v_flag = TABLEUPDATE(.T.)
  IF v_flag = .F. then
      LOCAL laError(1)  
      =AERROR(laError) 
      MESSAGEBOX(laError(1), 16, 'Ошибка')
  ELSE
      MESSAGEBOX('Новое значение сохранено', 64, 'ОК')
  ENDif


Во вьюхах на закладке Update Criteria поставил галочку Send SQL Updates выделил в качестве ключей поля, указал, что столбец field1 и filed2 (в зависимости от используемой в представлении таблицы) можно редактировать

Но всё равно возникли проблемы с обновлениями таблиц.
Причём tableupdate возвращает .T. (появляется сообщение, что новое значение сохранено) но на самом деле значения в любой таблице (их четыре по числу вариантов значения параметра nvar) не изменяются

Что я делаю не так?
ВладимирМ
Дата: 08.08.2012 13:57:23
А каким образом вызыватся метод Click()?

Если просто "нажали кнопку", то значения параметров будут пустыми. Как следствие, значение полей не изменится.

Для справки

Изменение полей текущей записи выполняется при помощи команды REPLACE. Например,

REPLACE field1 WITH lnValue


Если Вам надо узнать имя файла SCX, то этом можно сделать при помощи функции SYS(1271)

sele v_workdata

do case
case Upper(JustStem(Sys(1271,thisform))) == UPPER('f_first_form')
    REPLACE field1 WITH ThisForm.TextBox1.Value
case Upper(JustStem(Sys(1271,thisform))) == UPPER('f_second_form')
    REPLACE field2 WITH ThisForm.TextBox1.Value
endcase

v_flag = TABLEUPDATE(.T.)
IF v_flag = .F. then
      LOCAL laError(1)  
      =AERROR(laError) 
      MESSAGEBOX(laError(1), 16, 'Ошибка')
ELSE
      MESSAGEBOX('Новое значение сохранено', 64, 'ОК')
ENDif


Наконец, если указать в свойстве ControlSource объекта соответствующее поле таблицы, то модификация поля будет выполняться автоматически при изменении объекта на форме. В Click() кнопки надо будет всего-лишь дать команду TableUpdate().
Mr.Fontaine
Дата: 08.08.2012 14:45:37
малость не полно написал. код с tableupdate находится в отдельной процедуре, которая вызывается из Click с нужными параметрами. Так-то при отладке я вижу, что параметры не пустые (да хоть бы и пустые, тогда бы пусть бы null записывался бы)

В ControlSource прописан алиас (v_workdata), который собственно ссылается не на таблицу, а на вьюху. Непосредственно имя вюьхи (чтоб автоматом обновляло) прописать не могу, так как там может использоваться четыре разных представления. У которых обновляемые поля имеют разное название.

Replace думаю тут не повлияет на результат, так как после gather memvar, если открыть v_workdata в нужных полях стоят новые значения. А вот после TABLEUPDATE, несмотря на то, что вернулось .Т. в таблицах на сервере, на которые ссылаются вьюхи, спрятанные за алиасом v_workdata изменений никаких нет.
ВладимирМ
Дата: 08.08.2012 14:57:57
Mr.Fontaine
малость не полно написал. код с tableupdate находится в отдельной процедуре, которая вызывается из Click с нужными параметрами. Так-то при отладке я вижу, что параметры не пустые (да хоть бы и пустые, тогда бы пусть бы null записывался бы)

В случае пустых параметров в Вашем коде ни один IF не выполняется. Как следствие, нет никаких модификаций.

Mr.Fontaine
Replace думаю тут не повлияет на результат, так как после gather memvar, если открыть v_workdata в нужных полях стоят новые значения. А вот после TABLEUPDATE, несмотря на то, что вернулось .Т. в таблицах на сервере, на которые ссылаются вьюхи, спрятанные за алиасом v_workdata изменений никаких нет.

1. У Вас View создан на основе таблиц DBF или на основе других View? Сами исходные таблицы DBF находятся в каком-либо режиме буферизации? Т.е. не получается ли сброс буфера не в исходные таблицы, а в другой буфер, который надо дополнительно сбросить?

2. Можете привести листинг View из окна SQL дизайнера View?
Mr.Fontaine
Дата: 08.08.2012 15:58:46
1. таблицы на сервере MS SQL. Если буферизация определяется
SET MULTILOCKS ON 
= CURSORSETPROP('Buffering', 5, 'v_workdata' )

то я эти строчки писал перед scatter memvar не помогло. потом я их удалил. Может там какой парметр надо другой ставить, а не 5?

2. В листинге ничего интересного нет. Там условия с закладки Update Criteria не отображаются
SELECT *;
FROM dbo.first_plan first_plan;
WHERE first_plan.date = ?pp470;
ORDER BY first_plan.p083, first_plan.p015
ВладимирМ
Дата: 08.08.2012 16:16:52
В листинге итересует не сам запрос, а настройки DBSetProp(), чтобы не переспрашивать факт установки разных птичек и галочек в окне дизайнера View. Или у Вас версия младше VFP9?

Кстати, раз речь идет о MS SQL, то попробуйте в профайлере MS SQL отловить какая команда передается по команде TableUpdate().

И еще, приведенный код метода Click() - это все, что есть? Может, Вы даете команду TableUpdate() не на ту рабочую область? Попробуйте явным образом указать рабочую область примерно так

v_flag = TABLEUPDATE(.T., .T., "v_workdata")
Mr.Fontaine
Дата: 08.08.2012 16:27:56
ок. буду пробовать. завтра отпишусь
Mr.Fontaine
Дата: 09.08.2012 07:07:06
так-то работал не в 9-й версии. FoxPro 7 рабочая для этой программы. Посмотрел файл database.dbc с помощью девятки.
Получил листинг представления:
SELECT *;
 FROM ;
     dbo.first_plan first_plan;
 WHERE  first_plan.datec = ( ?pp470 );
 ORDER BY first_plan.p083, first_plan.p015

DBSetProp(ThisView,"View","Comment","* комментарий"+CHR(13))
DBSetProp(ThisView,"View","SendUpdates",.T.)
DBSetProp(ThisView,"View","BatchUpdateCount",1)
DBSetProp(ThisView,"View","CompareMemo",.T.)
DBSetProp(ThisView,"View","FetchAsNeeded",.F.)
DBSetProp(ThisView,"View","FetchMemo",.T.)
DBSetProp(ThisView,"View","FetchSize",100)
DBSetProp(ThisView,"View","MaxRecords",-1)
DBSetProp(ThisView,"View","Prepared",.F.)
DBSetProp(ThisView,"View","ShareConnection",.F.)
DBSetProp(ThisView,"View","AllowSimultaneousFetch",.F.)
DBSetProp(ThisView,"View","UpdateType",1)
DBSetProp(ThisView,"View","UseMemoSize",255)
DBSetProp(ThisView,"View","Tables","dbo.first_plan")
DBSetProp(ThisView,"View","WhereType",3)

DBSetProp(ThisView+".p015","Field","DataType","C(18)")
DBSetProp(ThisView+".p015","Field","UpdateName","dbo.first_plan.p015")
DBSetProp(ThisView+".p015","Field","KeyField",.T.)
DBSetProp(ThisView+".p015","Field","Updatable",.T.)

DBSetProp(ThisView+".p083","Field","DataType","C(15)")
DBSetProp(ThisView+".p083","Field","UpdateName","dbo.first_plan.p083")
DBSetProp(ThisView+".p083","Field","KeyField",.T.)
DBSetProp(ThisView+".p083","Field","Updatable",.T.)

DBSetProp(ThisView+".h528","Field","DataType","C(85)")
DBSetProp(ThisView+".h528","Field","UpdateName","dbo.first_plan.h528")
DBSetProp(ThisView+".h528","Field","KeyField",.F.)
DBSetProp(ThisView+".h528","Field","Updatable",.T.)

DBSetProp(ThisView+".vs","Field","DataType","N(16,2)")
DBSetProp(ThisView+".vs","Field","UpdateName","dbo.first_plan.vs")
DBSetProp(ThisView+".vs","Field","KeyField",.F.)
DBSetProp(ThisView+".vs","Field","Updatable",.T.)

DBSetProp(ThisView+".vsp","Field","DataType","N(16,2)")
DBSetProp(ThisView+".vsp","Field","UpdateName","dbo.first_plan.vsp")
DBSetProp(ThisView+".vsp","Field","KeyField",.F.)
DBSetProp(ThisView+".vsp","Field","Updatable",.T.)

DBSetProp(ThisView+".dater","Field","DataType","T")
DBSetProp(ThisView+".dater","Field","UpdateName","dbo.first_plan.dater")
DBSetProp(ThisView+".dater","Field","KeyField",.F.)
DBSetProp(ThisView+".dater","Field","Updatable",.T.)

DBSetProp(ThisView+".datec","Field","DataType","T")
DBSetProp(ThisView+".datec","Field","UpdateName","dbo.first_plan.datec")
DBSetProp(ThisView+".datec","Field","KeyField",.F.)
DBSetProp(ThisView+".datec","Field","Updatable",.T.)


Гляжу вроде всё нормально. Поля обновляемы, в свойствах вьюшки SendUpdates стоит true
А при выполнении TABLEUPDATE профайлер на SQL-сервере молчит.... Причём результат выполнения TABLEUPDATE возвращает true
Никак не могу понять, почему так происходит
Mr.Fontaine
Дата: 09.08.2012 07:18:09
Может быть проблема в том, что вьюшка называется database!v_fisrt_plan, а я обращаюсь к ней как v_workdata?
ВладимирМ
Дата: 09.08.2012 14:32:50
По описанию похоже на то, что команда TableUpdate() дается в другой рабочей области. Попробуйте явно указать где именно должен быть выполнен сброс буфера.

* Либо так
v_flag = TABLEUPDATE(.T., .T., "v_workdata")

* Либо так
select v_workdata
v_flag = TABLEUPDATE(.T.)


PS: Название объекта никакой роли не играет. Обращение идет либо по алиасу рабочей области, либо по таблице, открытой в текущей рабочей области. Весь вопрос в том, какая рабочая область текущая на момент подачи команды TableUpdate().