powered by simpleCommunicator - 2.0.55     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / FoxPro, Visual FoxPro [игнор отключен] [закрыт для гостей] / Редактирование документа, база данных на MSSQL.
7 сообщений из 7, страница 1 из 1
Редактирование документа, база данных на MSSQL.
    #36266226
dm_aks
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Используем технологию Pass-Through.
На клиенте после редактирования имеем 2 курсора master-detail, 1 запись в master,
в курсоре detail несколько записей было удалено, несколько отредактировано, несколько добавлено.
как организовать транзакцию на сервере?
...
Рейтинг: 0 / 0
Редактирование документа, база данных на MSSQL.
    #36266371
Ffffffffffffffff
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
dm_aksИспользуем технологию Pass-Through...

как организовать транзакцию на сервере?

Ну если уже используете...

Почитайте про Cursoradapter.
...
Рейтинг: 0 / 0
Редактирование документа, база данных на MSSQL.
    #36285895
dm_aks
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Ffffffffffffffff
Ну если уже используете...

Почитайте про Cursoradapter.

Опыта в клиент-серверных технологиях нет, Cursoradapter не исключаю, но сейчас выбор сделан
в пользу SPT.
Сделал пример

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
SET DELETED off
SET MULTILOCKS ON
SET TEXTMERGE ON
LOCAL lcStringConn, lnHandle, lcServer, lcDatabase, lcUser, lcPassWord, lcString, lcVar

* устанавливаем соединение с сервером
lcServer = "COMP1\MYSQLSERVER"
lcDatabase = "master"
lcUser = "sa"
lcPassWord = "555"
text to lcStringConn noshow pretext  15  
Driver=SQL Server; 
SERVER=<<lcServer>>; 
DATABASE=<<lcDatabase>>; 
uid=<<lcUser>>; 
pwd=<<lcPassWord>>; 
endtext 
lnHandle=SQLSTRINGCONNECT(lcStringConn)
if lnHandle<= 0  
  messagebox("Соединение не установлено!" + CHR( 10 ) + "Строка соединения:" + CHR( 10 ) + lcStringConn) 
  return 
endif 

* проверка наличия базы данных
lcString = [SELECT * FROM INFORMATION_SCHEMA.SCHEMATA WHERE CATALOG_NAME = 'TESTXXX']
res = SQL_EXEC("Запрос не выполнился:  " + lcString, lnHandle, lcString, "curs")
if res<= 0  
  SQLDISCONNECT(lnHandle)
  return
endif

*================= создание базы данных
IF EOF("curs")
text to lcString noshow pretext  15  
CREATE DATABASE TESTXXX ON (NAME = 'TESTXXX_db', 
	FILENAME = 'C:\TEST_XXX\TESTXXX.MDF')
endtext 
res = SQL_EXEC("Запрос на создание БД не выполнился!", lnHandle, lcString, "")
if res<= 0  
  SQLDISCONNECT(lnHandle)
  return
endif
text to lcString noshow pretext  15  
use TESTXXX
create table tMaster
(  tMaster_id int identity not null primary key,
   ndok int not null, 
   info varchar( 30 ) )
create table tDetail
(  tDetail_id int identity not null primary key,
   tMaster_id int not null foreign key references tMaster (tMaster_id),
   info1 varchar( 30 ),
   info2 varchar( 30 ) )
endtext 
res = SQL_EXEC("Запрос на создание таблиц БД не выполнился!", lnHandle, lcString, "")
if res<= 0  
  SQLDISCONNECT(lnHandle)
  return
endif
ENDIF 

*================= ввод первичных данных
text to lcString noshow pretext  15 
DECLARE @s int
use TESTXXX
DELETE FROM tDetail
DELETE FROM tMaster
INSERT into tMaster (ndok, info) values ( 1 , 'dokument N1')
SET @s = @@identity
INSERT into tDetail (tMaster_id, info1) values (@s, 'dok N1 - stroka N1')
INSERT into tDetail (tMaster_id, info1) values (@s, 'dok N1 - stroka N2')
INSERT into tDetail (tMaster_id, info1) values (@s, 'dok N1 - stroka N3')
INSERT into tMaster (ndok, info) values ( 2 , 'dokument N2')
SET @s = @@identity
INSERT into tDetail (tMaster_id, info1, info2) values (@s, 'dok N2 - stroka N1', 'info2')
INSERT into tDetail (tMaster_id, info1, info2) values (@s, 'dok N2 - stroka N2', 'info2')
INSERT into tDetail (tMaster_id, info1, info2) values (@s, 'dok N2 - stroka N3', 'info2')
INSERT into tMaster (ndok, info) values ( 3 , 'dokument N3')
SET @s = @@identity
INSERT into tDetail (tMaster_id, info1) values (@s, 'dok N3 - stroka N1')
INSERT into tDetail (tMaster_id, info1) values (@s, 'dok N3 - stroka N2')
INSERT into tDetail (tMaster_id, info1) values (@s, 'dok N3 - stroka N3')
endtext
res = SQL_EXEC("Запрос на ввод первичных данных в таблицы БД не выполнился!", lnHandle, lcString, "")
if res<= 0  
  SQLDISCONNECT(lnHandle)
  return
endif

*================= чтение документа
text to lcString noshow pretext  15 
DECLARE @mid int
use TESTXXX
SELECT * FROM tMaster WHERE ndok =  2 
SET @mid = (SELECT tMaster_id FROM tMaster WHERE ndok =  2 )
SELECT * FROM tDetail WHERE tMaster_id = @mid
endtext
res = SQL_EXEC("Запрос на чтение документа не выполнился!", lnHandle, lcString, "curs")
if res<= 0  
  SQLDISCONNECT(lnHandle)
  return
endif

*================= редактирование документа
SELECT curs
= CURSORSETPROP('Buffering',  5 )
browse
SELECT curs1
= CURSORSETPROP('Buffering',  5 )
browse
GO  2 
delete
GO  3 
REPLACE info1 WITH RTRIM(info1) + ">>update"
APPEND blank
REPLACE info1 WITH 'dok N2 - stroka XX>>append'
browse

**************** формирование команд для редактирования документа на сервере *****************
LOCAL lltMaster_Changed, lltDetail_Changed
SELECT curs
lltMaster_Changed = TableChanged()
SELECT curs1
lltDetail_Changed = TableChanged()
IF lltMaster_Changed OR lltDetail_Changed
text to lcString noshow pretext  7 
use TESTXXX
BEGIN TRANSACTION
ENDTEXT
SELECT curs
lndok_id = tMaster_id
IF lltMaster_Changed
text to lcVar noshow pretext  15 
UPDATE tDetail
SET info1 = '<<info1>>'
WHERE tMaster_id = <<lndok_id>>
ENDTEXT
lcString = lcString + CHR( 10 ) + lcVar
ENDIF
IF lltDetail_Changed
SELECT curs1
GO top
SCAN
DO case
case DELETED() AND !EMPTY(tDetail_id)
lcVar = "DELETE FROM tDetail WHERE tDetail_id = " + ALLTRIM(STR(tDetail_id))
lcString = lcString + CHR( 10 ) + lcVar
case EMPTY(tDetail_id)
text to lcVar noshow pretext  15 
INSERT into tDetail (tMaster_id, info1, info2) values (<<lndok_id>>, '<<info1>>', '<<info2>>')
ENDTEXT
lcString = lcString + CHR( 10 ) + lcVar
case RecordChanged()
text to lcVar noshow pretext  15 
UPDATE tDetail
SET info1 = '<<info1>>', info2 = '<<info2>>'
WHERE tDetail_id = <<tDetail_id>>
ENDTEXT
lcString = lcString + CHR( 10 ) + lcVar
ENDCASE
ENDSCAN
lcString = lcString + CHR( 10 ) + "COMMIT TRANSACTION"
messagebox("На сервер посылается набор строк:"+CHR( 10 )+lcString)
res = SQL_EXEC("Запрос на редактирование не выполнился!", lnHandle, lcString, "curs")
if res<= 0  
  SQLDISCONNECT(lnHandle)
  return
endif
ENDIF
ENDIF
**********************************************************************************************

SQLDISCONNECT(lnHandle)
RETURN

PROCEDURE SQL_EXEC(pmessage, pHandle, pString, pCurs)
LOCAL res
res = SQLEXEC(pHandle, pString, pCurs)
if res<= 0  
  AERROR(a)
  messagebox(pmessage+CHR( 10 )+"Ошибка номер"+STR(a( 1 ))+CHR( 10 )+a( 2 ), 0 ," ")
endif 
return res
ENDPROC
PROCEDURE TableChanged
IF ISNULL(GETFLDSTATE(- 1 ))
  RETURN .F.
ELSE
  RETURN ("2" $ GETFLDSTATE(- 1 ) OR ;
          "4" $ GETFLDSTATE(- 1 ))
ENDIF
ENDPROC
PROCEDURE RecordChanged 
LOCAL i , m_Field 
FOR i= 1  TO FCOUNT()
  m_Field = FIELD(i) 
  IF !(EVALUATE(m_Field) == OldVal(m_Field)) 
    RETURN .T. 
  ENDIF 
ENDFOR 
RETURN .F. 
ENDPROC

дайте оценку такого способа организации транзакции, какие альтернативные варианты?
...
Рейтинг: 0 / 0
Редактирование документа, база данных на MSSQL.
    #36289939
dm_aks
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
нашел логическую ошибку
текст

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
case DELETED() AND !EMPTY(tDetail_id)
lcVar = "DELETE FROM tDetail WHERE tDetail_id = " + ALLTRIM(STR(tDetail_id))
lcString = lcString + CHR( 10 ) + lcVar
case EMPTY(tDetail_id)
text to lcVar noshow pretext  15 
INSERT into tDetail (tMaster_id, info1, info2) values (<<lndok_id>>, '<<info1>>', '<<info2>>')
ENDTEXT
lcString = lcString + CHR( 10 ) + lcVar
case RecordChanged()
text to lcVar noshow pretext  15 
UPDATE tDetail
SET info1 = '<<info1>>', info2 = '<<info2>>'
WHERE tDetail_id = <<tDetail_id>>
ENDTEXT
lcString = lcString + CHR( 10 ) + lcVar
ENDCASE 

нужно заменить на:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
IF DELETED()      && запись удалена
  IF !EMPTY(tDetail_id)
    lcVar = "DELETE FROM tDetail WHERE tDetail_id = " + ALLTRIM(STR(tDetail_id))
    lcString = lcString + CHR( 10 ) + lcVar
  ENDIF
ELSE
  IF EMPTY(tDetail_id)      && запись добавлена
    text to lcVar noshow pretext  15 
    INSERT into tDetail (tMaster_id, info1, info2) values (<<lndok_id>>, '<<info1>>', '<<info2>>')
    ENDTEXT
    lcString = lcString + CHR( 10 ) + lcVar
  ELSE
    IF RecordChanged()      && запись изменена
      text to lcVar noshow pretext  15 
      UPDATE tDetail
      SET info1 = '<<info1>>', info2 = '<<info2>>'
      WHERE tDetail_id = <<tDetail_id>>
      ENDTEXT
      lcString = lcString + CHR( 10 ) + lcVar
    ENDIF
  ENDIF
ENDIF
...
Рейтинг: 0 / 0
Редактирование документа, база данных на MSSQL.
    #36296641
dm_aksИспользуем технологию Pass-Through.
На клиенте после редактирования имеем 2 курсора master-detail, 1 запись в master,
в курсоре detail несколько записей было удалено, несколько отредактировано, несколько добавлено.
как организовать транзакцию на сервере?

Не надо никаких курсор адаптеров. Каждое действие (удаление, изменение) должно сразу же уходить в соответствующую хранимую процедуру на сервере вместе с уникальным идентификатором фактурной строки и редактируемого документа в качестве параметров. В хранимках командами t-sql делаете всю работу, а по уникальному идентификатору основной части документа вызываете хранимку, которая пересчитывает у вас суммы в шапке документа.
...
Рейтинг: 0 / 0
Редактирование документа, база данных на MSSQL.
    #36296825
Fffffffffffffff
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Гениальный кодер
Не надо никаких курсор адаптеров.

Можно и так. И как автор написал, тоже можно. Но с курсорадаптером работы получается в три раза меньше.
...
Рейтинг: 0 / 0
Редактирование документа, база данных на MSSQL.
    #36297060
dm_aks
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Гениальный кодер
Не надо никаких курсор адаптеров. Каждое действие (удаление, изменение) должно сразу же уходить в соответствующую хранимую процедуру на сервере вместе с уникальным идентификатором фактурной строки и редактируемого документа в качестве параметров. В хранимках командами t-sql делаете всю работу, а по уникальному идентификатору основной части документа вызываете хранимку, которая пересчитывает у вас суммы в шапке документа.

Спасибо, это один из ключевых моментов, почему нужно сохранять каждую запись, а не документ в целом?
Независимо от используемой технологии, тем более на форме одна кнопка 'Save' для сохранения документа.
...
Рейтинг: 0 / 0
7 сообщений из 7, страница 1 из 1
Форумы / FoxPro, Visual FoxPro [игнор отключен] [закрыт для гостей] / Редактирование документа, база данных на MSSQL.
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]