IBDatabase ApplyUpdate

11 отговора 332 прегледа
#1

IBDatabase ApplyUpdate

Въпроса ми е следния: иаползвам IBQuery за манипулиране на данните от Interbase database.Данните визуализирам в DBGrid.При инсертване на запис, за постването му на сървара използвам метода ApplyUpdate след който данните в грида се опресняват, т.е. визуализира се въведения запис.Забравих да спомена че CachedUpdate на IBQuery е FALSE.Ако обаче редактирам току що въведения запис се получава грешка.Ако обаче реконектна връзката с БД редакцията се получава без грешка.Ако Направя CachedUpdate на True всичко е наред и не се налага реконект на връзката с БД.Също ако в събитието OnPost на IBQuery-to извикам методите Close а след това Open на IBQuery-to пак всичко е наред.Кой е най добрия подход за да може хем нововъведените данни да се постнат на сървара хем да се опресни грида и да може веднага да се редактират данните.
Другият ми въпрос е свързан с транзакциите.
Какво е състоянието на IBQuery-tata след commit и rollback на транзакцията а също и състоянието на транзакзията.

Отговор
в отговор на lOs #2

Re: IBDatabase ApplyUpdate

Като цяло не правиш нещата както трябва. ApplyUpdates се използва само за CachedUpdates. Когато не си в режим на CachedUpdates промените по данните се изпращат към сървъра при викането на методите Post и Delete. Също така не е необходимо да изпъляваш наново заявката, за да ти се опреснят данните в грида. Твоите промени ще се видят автоматично. Виж, ако искаш да видиш промени, които са направени от друг потребител - да, но не мисля, че този начин е най-подходящият.
На въпроса ти за състоянието на кюрито и транзакцията след commit/rollback - ами кюритата ти се затварят, а транзакцията завършва. За да продължиш работа трябва да пуснеш нова транзакция и да си отвориш кюрито. По друг начин са нещата, ако използваш commitretaining/rollbackretaining. Тогава може да се каже, че транзакцията завършва, пуска се нова такава и това не ти затваря кюрито.
Нека да обобщим нещата. За да използваш кюри, което визуализира данните в грид и да ги редактираш (при условие, че CachedUpdates=False) трябва да имаш активна транзакция (дали ти ще си я пуснеш сега или ще е активна от по-рано зависи от логиката на приложението ти). Добавянето на запис става с метода Append, след което присвояваш стойности на колоните и накрая викаш метода Post. Редактирането на данните е аналогично, но в началото викаш метода Edit. Изтриването на запис става с Delete. Да уточня, че за да е възможно това нещо с IBQuery трябва да си закачил IBUpdateSQL и да си попълнил правилно SQL-ите.
След редакцията на данните, би могъл да приключиш транзакцията. Това става Commit/CommitRetainig. При вторият случай можеш да продължиш с редакциите, докато в първия ще трябва да си отвориш наново кюрито.
Извинявай, че бях толкова многословен. Надявам се не съм те объркал твърде много
Ако има нещо неясно - питай!

Отговор
в отговор на andrew_nikoloff #3

Re: IBDatabase ApplyUpdate

Благодаря за изчерпателния отговор.Добре че попитах иначе както се оказа съм тръгнал в грешна посока.Още един път thank's.

Отговор
в отговор на andrew_nikoloff #4

Re: IBDatabase ApplyUpdate

Вместо ApplyUpdate викам Post на Query-to. Новият запис се визуализира в грида, но ако взема веднага да го редактирам дава грешка.На сървъра записа несъществува докато не реконектна връзката с БД.Транзакциата ми е стартирана и си остава такава и след като постна записа.Защо новият запис не се съхранява веднага на сървъра?CashedUpdate на Query-to е False. Сигурно пак бъркам някъде.

Отговор
в отговор на lOs #5

Transaction isolation level

Първо кажи каква грешка ти дава, че съм си забравил кристалната топка в къщи
А за липсата на записа от сървъра - мисля, че той си е там, но ти не можеш да го видиш, защото го гледаш от друга транзакция, а транзакцията на твоята програма не позволява да се виждат промените до приключването й. DblClick-ни Transaction компонента ти и избери ReadCommited. Също така ако не ти е необходимо да държиш транзакцията е много желателно да я Commit-неш (или поне CommitRetaining). След това ще можеш да си видиш записа в базата.

А за грешката - като кажеш каква е ще мога да ти кажа повече...

Отговор
в отговор на andrew_nikoloff #6

Re: Transaction isolation level

Ако правилно съм разбрал от всичко казано до тук, трябва да използвам следния код:

trMyTransaction.StartTrnsaction;
qry.Append;
qry.FieldByName('...').As.... := ....;
.....
qry.FieldByName('...').As... := ...;
try
qry.Post;
trMyTransaction.Commit
except
trMyTransaction.Rollback
end;


ако нещо бъркам ме поправи.
А за грешката ако я постна ще трябва да постна и структурата на танлицата и самата заявка и ще стане много дълго за обяснение ако въобще успея да го обясня.Мисля че ще се справя с грешката ако съм разбрал всичко правилно и горния код е коректен.

Отговор
в отговор на lOs #7

Принципно е така

По принцип последователността е такава. Само ще те посъветвам да промениш малко кода.

if trMyTransaction.InTransaction then trMyTransaction.Commit; //Проверка за активна транзакция. Иначе ще ти изгърми кода.
trMyTransaction.StartTrnsaction;
try
qry.Open; //След Commit дейтасетите са ти затворени. Иначе трябва да ползваш CommitRetaining
qry.Append;
qry.FieldByName('...').As.... := ....; //Ако си добавиш фийлдовете дизайнтайм можеш да работиш и с qryID.AsInteger := 1 например, което е малко по-бързо и няма опастност да сбъркаш името на фийлда и да не го разбереш още по време на компилация.
.....
qry.FieldByName('...').As... := ...;
qry.Post;
trMyTransaction.Commit;
except
trMyTransaction.Rollback;
raise; //или по някакъв друг начин да се разбере, че се е случила грешка. Например MessageDlg
end;


Отговор
в отговор на andrew_nikoloff #8

Re: Принципно е така

Новият запис се визуализира в грида, но ако не се затвори и отвори отново Query-to, т.е. заявката да се изпълни отново и да върне новия запис като резултат, не може да се редактира новия запис.Той присъства в грида и на сървара но не го е върнала заявката и когато при редакция на този запис(маркера на грида сочи към този запис, когато се извиква метода Edit на Query-to) полетата, които не се променят а остават същите, при Post се появява грешка че тези полета нямат стойности. Exception-a има следния текст: 'EIBInterbaseError - validation error for column SomeColumn(която не се променя при редакцията), value "***null***"".'
Ако заявката се изпълни отново всичко е ок.

А сега накъде?

Отговор
в отговор на lOs #9

SelectSQL и RefreshSQL

Сега вземи да постнеш във форума SelectSQL и RefreshSQL-ите на кюрито и UpdateSQL-а, защото си мисля, че нещо RefreshSQL-а не ти е наред.

Отговор
в отговор на andrew_nikoloff #10

Re: SelectSQL и RefreshSQL

Това е от UpdateSQL компонентата:

update STOCKS
set
STOCK_ID = :STOCK_ID,
CODE = :CODE,
DESCRIPTION = :DESCRIPTION,
MEASURE_ID = :MEASURE_ID,
SALE_PRICE = :SALE_PRICE,
SGROUP_ID = :SGROUP_ID
where
STOCK_ID = :OLD_STOCK_ID

insert into STOCKS
(STOCK_ID, CODE, DESCRIPTION, MEASURE_ID, SALE_PRICE, SGROUP_ID)
values
(:STOCK_ID, :CODE, :DESCRIPTION, :MEASURE_ID, :SALE_PRICE, :SGROUP_ID)

delete from STOCKS
where
STOCK_ID = :OLD_STOCK_ID

Select
STOCK_ID,
DESCRIPTION,
MEASURE_ID,
SALE_PRICE,
SGROUP_ID,
CODE
from STOCKS
where
STOCK_ID = :STOCK_ID


А ето и самата завка:

SELECT STOCKS.STOCK_ID, STOCKS.CODE, STOCKS.DESCRIPTION,
STOCKS.MEASURE_ID, STOCKS.SALE_PRICE, SGROUPS.GROUP_ID, STOCKS.SGROUP_ID,
MEASURES.NAME
FROM STOCKS
INNER JOIN SGROUPS ON (STOCKS.SGROUP_ID = SGROUPS.SGROUP_ID)
INNER JOIN MEASURES ON (STOCKS.MEASURE_ID = MEASURES.MEASURE_ID)


Отговор
в отговор на lOs #11

Две неща

1. RefreshSQL-а трябва да ти е

SELECT STOCKS.STOCK_ID, STOCKS.CODE, STOCKS.DESCRIPTION,
STOCKS.MEASURE_ID, STOCKS.SALE_PRICE, SGROUPS.GROUP_ID, STOCKS.SGROUP_ID,
MEASURES.NAME
FROM STOCKS
INNER JOIN SGROUPS ON (STOCKS.SGROUP_ID = SGROUPS.SGROUP_ID)
INNER JOIN MEASURES ON (STOCKS.MEASURE_ID = MEASURES.MEASURE_ID)
where
STOCKS.STOCK_ID = :STOCK_ID


2. Как си генерираш стойностите за STOCK_ID? С тригер предполагам? Използвай генератор и GeneratorField пропъртито на кюрито.

Направи тези неща и кажи какво е станало.

Отговор
в отговор на andrew_nikoloff #12

Re: Две неща

На въпроса как генерирам стойностите на STOCK_ID?
- ползвам генератор и тригер BeforeInsert, както си предположил.
Промених SQL-a на Refresh-a както ме посъветва и всичко заработи перфектно.
Благодаря за съветите.

Отговор