Volání metody obsahující transakci uvnitř transakce

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
raketoplan2005
Člen | 147
+
0
-

Ahoj,

mám v Nette\Database otevřenou transakci, ve které volám metodu, která také využívá transakce (může fungovat i samostatně, proto je transakce nutná).

Tím ale vzniká problém s:

PDOException
There is already an active transaction

Jak se lze tomuto problému vyhnout, bylo by popř. možné rozšířit Nette\Database o něco podobného jako popisuje autor? Dědit si kvůli tomu vlastní NDB je asi hloupost.

enumag
Člen | 2118
+
0
-
if (!$connection->inTransaction) {
	$connection->beginTransaction();
}
raketoplan2005
Člen | 147
+
0
-

To ale nezafunguje kdybych měl funkci poskládanou takhle

  • udělej něco
  • zavolej jinou metodu
  • udělej něco dalšího

a to vše v transakci, protože mi commit v té metodě už transakci zavře.

Editoval raketoplan2005 (6. 1. 2013 12:21)

Arynev
Člen | 33
+
0
-

Tak si vytvoř v nějakém base modelu obalovací funkce nad transakcema jako v tom komentáři

enumag
Člen | 2118
+
+1
-

V tom případě si budeš muset podědit \Nette\Database\Connection dle toho kódu co z php.net:

class MyConnection extends \Nette\Database\Connection
{

    /** @var int */
    protected $transactionCounter = 0;

    public function beginTransaction()
    {
        if (!$this->transactionCounter++) {
            return parent::beginTransaction();
        }
    }

    public function commit()
    {
       if (!--$this->transactionCounter) {
           return parent::commit();
       }
    }

    public function rollback()
    {
        $this->transactionCounter = 0;
        if ($this->inTransaction()) {
            return parent::rollback();
        }
    }

}

Editoval enumag (6. 1. 2013 12:29)

raketoplan2005
Člen | 147
+
0
-

Takto to vyřeším, jen jsem si chtěl být jistý, že jsem nepřehlédnul jinou možnost, nebo feature Nette\Database, která by tenhle problém řešila. Možná by se to do budoucna součástí Nette\Database stát mohlo?

enumag
Člen | 2118
+
0
-

To nepovažuji za pravděpodobné. Kdo to chce, může si to takto snadno napsat a ani není potřeba žádný hack. Dává mi to lepší smysl jako samostatná věc. Možná to také použiju, pokud ano, vytvořím gist.

duke
Člen | 650
+
0
-

Pokud používáš databázi, která podporuje savepointy, lze tento problém řešit rozšířením Nette\Database\Connection podobně jako to vyřešili zde pro PDO.

raketoplan2005
Člen | 147
+
0
-

Vím že je to částečně OT, ale poradili byste mi, prosím, jak pozměním config aby pracoval s odděděnou třídou Connection?

Mám:

common:
	nette:
		database:
			default:
				dsn: 'mysql:host=XXX;dbname=XXX'
				user: 'XXX'
				password: 'XXX'
				debugger: true # panel v Debugger baru
				explain: true  # explain dotazů v Debugger baru
				reflection: discovered
				cache: @cacheStorage
	services:

		database:
			@nette.database.default

Když přesunu přístupové údaje do parameters a v services nastavím vlastní třídu (zrovna duke to takto řešil), tak tam ale nedokážu předat více než dsn, užvatele a heslo, další parametr je pole options. Jak nastavím debugger, explain, reflection a cache?

services:
    nette.database.default:
        class: MyConnection
        arguments:
            - %database.default.dsn%
            - %database.default.user%
            - %database.default.password%

Editoval raketoplan2005 (6. 1. 2013 18:55)

enumag
Člen | 2118
+
0
-

Řekl bych že takto:

common:
    nette:
        database:
            default:
                debugger: true
                explain: true
                reflection: discovered
                cache: @cacheStorage
    services:
        nette.database.default:
            class: MyConnection
            arguments:
                - %database.default.dsn%
                - %database.default.user%
                - %database.default.password%

Editoval enumag (6. 1. 2013 20:55)

raketoplan2005
Člen | 147
+
0
-

Děkuji, všem.

Editoval raketoplan2005 (6. 1. 2013 21:46)