Slevový týden - Srpen
30 % bodů zdarma na online výuku díky naší Slevové akci!
Pouze tento týden sleva až 80 % na e-learning týkající se Javy.
Avatar
skilledt
Člen
Avatar
skilledt:11.6.2019 10:11

Zdravím, vyvíjím webovou službu(Web service), kde v rámci jedné web methody provádím několik hned několik sql insert a update operací. Potřebuji zajistit aby všechny operace proběhly v pořádku nebo aby neproběhly vůbec, takže jsem použil transakce.
U každé sql operace tedy kontroluji zda proběhla a v případě že ne vyvolám rollback a SoapException. Problém ovšem je, jak ošetřit neočekávané chyby, které nastanou jinde v kódu, při kterých dojde k chybě, ale vlastně rollback neproběhne, transakce zůstane viset a dojde k locku databáze. Jak se řeší tyto případy?

Zkusil jsem: Napadlo mě část kódu metody, kde probíhají sql operace obalit do try blocku a na konec dát finally, ve kterém provedu rollback, ale zdá se mi to jako dost kostrbaté řešení, dávat velkou část kódu do try blocku.
Dále jsem zkoušel transakci užít v rámci using blocku, a uvnitř něj provádět operace, to problém vyřešilo, ale zas to hází chybu v případě, že vše proběhne v pořádku a transakce je commitnuta(konec using blocku pak nemá na čem provést dispose a dojde k chybě "žádná uživatelská transakce nebyla nalezena") .

 
Odpovědět
11.6.2019 10:11
Avatar
Jaroslav Smrž
Redaktor
Avatar
Odpovídá na skilledt
Jaroslav Smrž:11.6.2019 10:28

Mně přijde řešení v try bloku celkem logické a v pořádku. Řešil bych to nějak podobně:

try {
// sql dotazy
// na konci zavolat commit
// hláška o úspěchu
return true;
}

catch(vyjimka) {
// zde vyhodit vyjímku
// provest rollback
// ukoncit
}
Akceptované řešení
+20 Zkušeností
+1 bodů
Řešení problému
Nahoru Odpovědět
11.6.2019 10:28
/* Life runs on code */
Avatar
Jaroslav Smrž
Redaktor
Avatar
Odpovídá na skilledt
Jaroslav Smrž:11.6.2019 10:35

sorry, vyjímku vyhodit po rollbacku do hlášky

Nahoru Odpovědět
11.6.2019 10:35
/* Life runs on code */
Avatar
skilledt
Člen
Avatar
Odpovídá na Jaroslav Smrž
skilledt:11.6.2019 11:13

Dobře, děkuji za odpověď. Měl jsem za to, že nějaké delší try blocky jsou bad practice, ale pravda, asi to jinak obejít moc nelze.

 
Nahoru Odpovědět
11.6.2019 11:13
Avatar
Jaroslav Smrž
Redaktor
Avatar
Odpovídá na skilledt
Jaroslav Smrž:11.6.2019 12:22

Není za co. Jsem rád, že ti to pomohlo. Zkus třeba ještě prostudovat dokumentaci k transactions, ale podle mně to ani jinak udělat nejde. Něco podobného jsem řešil minulý rok a dodnes vše běží v pořádku.

Nahoru Odpovědět
11.6.2019 12:22
/* Life runs on code */
Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!
Avatar
Odpovídá na skilledt
don.jarducius:12.6.2019 10:31

Ještě je jeden způsob:

using (SqlConnection conn = new SqlConnection("connectionString"))
using (SqlTransaction tran = conn.BeginTransaction())
{
    // SQL dotazy
    // ...
    tran.Commit();
}

Tím, že to uzavřeš do using(...) dojde i u vyhození vyjímky k volání Dispose na Transakci (při tom se provede RollBack), k volání Dispose/Close na SqlConnection a následně se exception probublá výš.

PS: Totožný dotaz na StackOverflow

Nahoru Odpovědět
12.6.2019 10:31
Ten kdo nechce hledá důvod, ten kdo chce hledá způsob
Avatar
Odpovídá na skilledt
don.jarducius:12.6.2019 10:35

EDT: "žádná uživatelská transakce nebyla nalezena" ti nevyhodí dispose na konci using bloku ale provedení commit/rollback na již dokončené transakci.

Nahoru Odpovědět
12.6.2019 10:35
Ten kdo nechce hledá důvod, ten kdo chce hledá způsob
Avatar
skilledt
Člen
Avatar
Odpovídá na don.jarducius
skilledt:12.6.2019 16:22

To jsem také zkoušel a opravdu mi tu chybu vyhazuje konec using blocku ve chvíli, kdy proběhne commit těsně před koncem using blocku.

Editováno 12.6.2019 16:23
 
Nahoru Odpovědět
12.6.2019 16:22
Avatar
Odpovídá na skilledt
don.jarducius:12.6.2019 16:28

Takhle používám transakce běžně, nic takového mi to nehlásí... Používáš synchronní nebo asynchronní metody? Můžeš sem dát úryvek toho kódu?

Nahoru Odpovědět
12.6.2019 16:28
Ten kdo nechce hledá důvod, ten kdo chce hledá způsob
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 9 zpráv z 9.