Article View: pl.comp.lang.delphi.bazy-danych
Article #82045Re: Transakcje MSSQL2008, ANYDAC
From: wloochacz
Date: Thu, 24 Apr 2014 19:44
Date: Thu, 24 Apr 2014 19:44
161 lines
7159 bytes
7159 bytes
W dniu 2014-04-18 22:32, feniks pisze:
> Witam
>
> Zasadniczo moim celem jest zabezpieczenie operacji i przy wystąpieniu jakiegokolwiek problemu wycofanie całej operacji i poinformowanie użytkownika, iż coś jest nie tak.
OK, bo mnie lesioq wk (widzisz jaki ze mnie prosty chłop, tak łatwo daję
sie podejść) to Ci napiszę co i jak ;-)
> Życie pokazało, iż to mi się nie udało dlatego zwracam się z uprzejma prośbą o pomoc, pokazanie jak taki kod powinien wyglądać
> Umieszczony kod jest częścią kodu właściwego z dużą ilością warunków i aby pokazać to co dla mnie ważne w tym poście część linijek wyciąłem i trochę za dużo gdyż jak słusznie Pan zauważył brakuje DM.up.sql.Clear.
Pytanie #1:
Czy CachedUpdates dla jest w ogóle włączone?
czyli DM.dane.Cachedudpates := True; ??
Zakładam, że tak jest...
Pytanie #2:
Wiesz czym jest i jak działa CachedUpdates?
Jesli nie wiesz, to spójrz:
http://docwiki.embarcadero.com/Libraries/XE6/en/FireDAC.Comp.DataSet.TFDDataSet.CachedUpdates
Na początek wystarczy to zdanie: "CachedUpdates enables (True) or
disables (False) the logging of data changes (Insert/Post, Edit/Post,
Delete) without immediately applying them to the database."
A więc wszelkie zmiany w DataSecie (DM.dane), które robisz za pomocą
Insert/Append, Edit, Delete nie "wchodzą" do bazy danych. Dane są
zmieniane (i logowane - jest też mechanizm Undo/Redo oraz SavePoints -
lesioq wyjaśni Ci co są te SavePointy w kontekście Nested Transaction,
bo on to wrzuca do T-SQL'a) tylko i wyłącznie w lokalnym buforze DataSetu.
Żeby zmiany z lokalnego bufora poleciały do bazy danych, należy wywołać:
ApplyUpdates - do zatwierdzenia zmian.
CommitUpdates - kasuje log zmian dla rekordów z lokalnego bufora
DataSetu i oznacza wszystkie rekordy jako niezmodyfikowane (ciekaowstka
- w AnyDAC/FireDAC jest mechnizm typu row-level-versioning, ale to inna
bajka...)
CancelUpdates - do anulowania zmian.
OK, tyle wstępu...
Pierwszy problem, to wywolanie ApplyUpdates - napisałeś tak:
DM.dane.ApplyUpdates;
Ale ApplyUpdates zadeklarowano tak:
function ApplyUpdates(AMaxErrors: Integer = -1): Integer;
AMaxErrors odpowiada ile błędów jest dopuszczone podczas aktualizacji
danych w bazie. -1 oznacza - bez limitu, co sprawia, że ApplyUpdates
aktulizuje dane w bazie na podstawie logu zmian w DataSecie - wiersz po
wierszu. Jeśli w momencie aktualizacji (czyli kiedy wołasz ApplyUpdates)
wiersza wystąpi wyjątek (z różnych powodów, np. naruszenie klucza,
wartośc null dla pola not-null, albo zaniku połączenia z serwerem), to
dzieje się tak:
1) Jeżeli AMaxErrors < 0, to nie przejmuj się i przejdź do aktulizacji
następnego wiersza.
2) Jeśli był bład, to wołaj zdarzenie OnReconcileError
Zatem, Twój kod powinien być napisany tak (ale to wersja biedna, bo nie
powinno być częściowych aktualkizacji w bazie ale nadal nie będziesz
widział co poszło nie tak):
var
lErrorCount: Integer;
begin
DM.ADConnection1.StartTransaction;
try
if DM.dane.State in dsEditModes then
DM.dane.Post;
if DM.dane.UpdatesPending then
begin
lErrorCount := DM.dane.ApplyUpdates(0);
if lErrorCount = 0 then
DM.dane.CommitUpdates;
end
else
lErrorCount := 0;
if lErrorCount = 0 then
begin
DM.up.sql.Text := 'UPDATE prac_war SET s_wn = s_wn+:zkw WHERE
prac_war.SYMBOL_P = :zsymbol_p';
DM.up.ParamByName('zkw').Value := zkwota_s;
DM.up.ParamByName('zsymbol_p').Value := zsymbol_p;
DM.up.ExecSQL;
DM.ADConnection1.Commit;
end
else
DM.ADConnection1.Rollback;
except
DM.ADConnection1.Rollback;
MessageBox(Handle, 'Operacja nie powiodła się !!!!', 'Błąd', mb_OK
+ MB_ICONSTOP);
end;
end;
Jeśli chcesz dowiedzieć się co poszło ni tak, masz kilka opcji:
1) Obsłużyć zdarzenie OnUpdateErrror
2) Obsłużyć zdarzenie OnReconcileError
3) Użyć FilterChanges
Pokażę z tą trzecią opcją, czyli:
var
lErrorCount: Integer;
lST : TStringList;
begin
DM.ADConnection1.StartTransaction;
try
if DM.dane.State in dsEditModes then
DM.dane.Post;
if DM.dane.UpdatesPending then
begin
lErrorCount := DM.dane.ApplyUpdates(-1);
if lErrorCount = 0 then
DM.dane.CommitUpdates;
end
else
lErrorCount := 0;
if lErrorCount = 0 then
begin
DM.up.sql.Text := 'UPDATE prac_war SET s_wn = s_wn+:zkw WHERE
prac_war.SYMBOL_P = :zsymbol_p';
DM.up.ParamByName('zkw').Value := zkwota_s;
DM.up.ParamByName('zsymbol_p').Value := zsymbol_p;
DM.up.ExecSQL;
DM.ADConnection1.Commit;
end
else
begin
DM.dane.FilterChanges := [rtModified, rtInserted, rtDeleted,
rtHasErrors];
lST := TStringList.Create;
try
DM.dane.First;
while not DM.dane.Eof do
if Assigned(DM.dane.RowError) then
lST.Add(DM.dane.RowError.Message);
if lST.Count > 0 then
MessageBox(Handle, 'Operacja nie powiodła się !!!!'#13#10 +
lST.Text, 'Błąd', mb_OK + MB_ICONSTOP);
finally
lST.Free;
DM.dane.FilterChanges := [rtUnmodified, rtModified, rtInserted];
DM.ADConnection1.Rollback;
end;
end;
except
DM.ADConnection1.Rollback;
MessageBox(Handle, 'Operacja nie powiodła się !!!!', 'Błąd', mb_OK
+ MB_ICONSTOP);
end;
end;
PS.
Nie sprawdzałem kodu, może nie działać od ręki...
--
wloochacz
Technical Details
Message-ID:
<535969af$0$2246$65785112@news.neostrada.pl>Path:
mbox-mo1.pugleaf.net!news-archive.icm.edu.pl!agh.edu.pl!news.agh.edu.pl!newsfeed2.atman.pl!newsfeed.atman.pl!news.nask.pl!news.nask.org.pl!news.unit0.net!usenet.blueworldhosting.com!feeder01.blueworldhosting.com!peer01.iad.highwinds-media.com!news.highwinds-media.com!feed-me.highwinds-media.com!nx01.iad01.newshosting.com!newshosting.com!newsfeed.neostrada.pl!unt-exc-01.news.neostrada.pl!unt-spo-a-01.news.neostrada.pl!news.neostrada.pl.POSTED!not-for-mailReferences:
<c776d48b-fec7-421f-89f2-fbed5ec8f316@googlegroups.com> <5350f511$0$2246$65785112@news.neostrada.pl> <1383d8eb-5c02-40aa-bc0e-60f9c1b9dd7b@googlegroups.com>Show Full Headers
Complete Article Headers
Path: mbox-mo1.pugleaf.net!news-archive.icm.edu.pl!agh.edu.pl!news.agh.edu.pl!newsfeed2.atman.pl!newsfeed.atman.pl!news.nask.pl!news.nask.org.pl!news.unit0.net!usenet.blueworldhosting.com!feeder01.blueworldhosting.com!peer01.iad.highwinds-media.com!news.highwinds-media.com!feed-me.highwinds-media.com!nx01.iad01.newshosting.com!newshosting.com!newsfeed.neostrada.pl!unt-exc-01.news.neostrada.pl!unt-spo-a-01.news.neostrada.pl!news.neostrada.pl.POSTED!not-for-mail Date: Thu, 24 Apr 2014 21:44:22 +0200 From: wloochacz <wloochacz@no.spam.gmail.com> User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:24.0) Gecko/20100101 Thunderbird/24.4.0 MIME-Version: 1.0 Newsgroups: pl.comp.lang.delphi.bazy-danych Subject: Re: Transakcje MSSQL2008, ANYDAC References: <c776d48b-fec7-421f-89f2-fbed5ec8f316@googlegroups.com> <5350f511$0$2246$65785112@news.neostrada.pl> <1383d8eb-5c02-40aa-bc0e-60f9c1b9dd7b@googlegroups.com> In-Reply-To: <1383d8eb-5c02-40aa-bc0e-60f9c1b9dd7b@googlegroups.com> Lines: 161 Message-ID: <535969af$0$2246$65785112@news.neostrada.pl> Organization: Telekomunikacja Polska NNTP-Posting-Host: 83.25.255.13 X-Trace: 1398368688 unt-rea-b-01.news.neostrada.pl 2246 83.25.255.13:14854 X-Complaints-To: abuse@news.neostrada.pl X-Received-Bytes: 6845 X-Received-Body-CRC: 3363227285 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit