2009. június 2., kedd

LINQ to SQL vs. Tranzakciók

A .NET Framework 2.0-ás verziójától (azaz elég régóta) két lehetőségünk van tranzakciók kezelésére: az ADO.NET-féle, IDbTransaction implementációkra alapuló megoldás, illetve a System.Transactions.dll-ben lakó, hasonló nevű névtér alatt található osztályokra támaszkodó verzió (ügyfélkódban leginkább a TransactionScope osztállyal talákozhattunk).
Igazából nem is kétféle lehetőségünk van, hanem három, mert ott volt még az Enterprise Services-féle megoldás is, de most se ebbe, se az előbbi kettő működésébe nem mennék bele, mert a probléma, ami e post írására sarkallt, az az, hogy ezeket a tranzakció-kezelési megoldásokat hogy lehet a LINQ to SQL-lel összeházasítani.

A rövid válasz: szerencsére könnyen. :)
A kicsit hosszabb válasz az, hogy mind az ADO.NET-es, mind a System.Transactions-ös tranzakciók támogatottak, de mindkettő másképp. LINQ to SQL-ről lévén szó, nem nagy meglepetés, hogy a DataContext osztály körül fogunk pörögni, hiszen ez az a "központi" oszály, aminek segítségével az adatforrásunkból lekérdezve, vagy a SubmitChanges() által oda a változtatásainkat visszaírva a háttérben SQL műveleteket tudunk végrehajtani - márpedig mi pont ezeket a műveleteket szeretnénk tranzakcionálisan végrehajtani.

Az első esetben a DataContext osztályunk Transaction property-jét kell beállítani arra az IDbTransaction példányra, amiben részt szeretnénk venni:

IDbTransaction transaction; // ez jön valahonnan...

using (var db = new MyDataContext())
{
    db.Transaction = transaction;

    // DB mókolás...
    db.SubmitChanges();

    // további változtatások...
    db.SubmitChanges();
}

// Ne felejtsünk el kommitálni, amikor kell...
transaction.Commit();
Ebben az esetben, ha a Transaction property-t valamilyen nem-null értékre állítjuk, a LINQ to SQL megteszi azt a szívességet, hogy nem zárja le a DataContext osztályunkhoz tartozó connection-t.

A másik lehetőség a System.Transactions.TransactionScope osztály használata.
Ebben az esetben még egyszerűbb dolgunk van, ugyanis semmit nem kell tennünk (legalábbis semmi olyat, amit egy "normál" adatrétegben ne kéne amúgy is). A LINQ to SQL érzékelni fogja, hogy egy TransactionScope-ban lett hívva az API valamely (teszemazt a SubmitChanges()) metódusa, és abban a scope-ban fog végrehajtódni. Az adatbázis-kapcsolatunk ebben az esetben is nyitva marad.

Érdemes még tudni, hogy a LINQ to SQL akkor is tranzakcionálisan perzisztálja le a változtatásainkat, ha nem adunk meg explicit tranzakciót. Ilyen esetben (tehát ha a Transaciton property null, TransactionScope pedig nincs), akkor a LINQ to SQL maga nyit egy ADO.NET tranzakciót, és azon belül próbálja végrehajtani a változtatásainkat.

0 megjegyzés:

Megjegyzés küldése