Bagaimana TransactionScope memutar balik transaksi?

99

Saya sedang menulis tes integrasi di mana saya akan memasukkan sejumlah objek ke dalam database dan kemudian memeriksa untuk memastikan apakah metode saya mengambil objek tersebut.

Koneksi saya ke database adalah melalui NHibernate ... dan metode saya yang biasa untuk membuat tes semacam itu adalah dengan melakukan hal berikut:

NHibernateSession.BeginTransaction();

//use nhibernate to insert objects into database
//retrieve objects via my method
//verify actual objects returned are the same as those inserted

NHibernateSession.RollbackTransaction();

Namun, baru-baru ini saya mengetahui tentang TransactionScope yang ternyata dapat digunakan untuk tujuan ini ...

Beberapa contoh kode yang saya temukan adalah sebagai berikut:

public static int AddDepartmentWithEmployees(Department dept)
{

    int res = 0;

    DepartmentAdapter deptAdapter = new DepartmentAdapter();
    EmployeeAdapter empAdapter = new EmployeeAdapter();
    using (TransactionScope txScope = new TransactionScope())
    {

        res += deptAdapter.Insert(dept.DepartmentName);
        //Custom method made to return Department ID 
        //after inserting the department "Identity Column"
        dept.DepartmentID = deptAdapter.GetInsertReturnValue();
        foreach(Employee emp in dept.Employees)
        {

            emp.EmployeeDeptID = dept.DepartmentID;
            res += empAdapter.Insert(emp.EmployeeName, emp.EmployeeDeptID);

        }
        txScope.Complete();

    }
    return res;

}

Saya percaya bahwa jika saya tidak menyertakan baris txScope.Complete()yang disisipkan data akan dibatalkan. Tapi sayangnya saya tidak mengerti bagaimana itu mungkin ... bagaimana txScopeobjek melacak deptAdapterdan empAdapterobjek dan transaksinya di database.

Saya merasa seperti saya kehilangan sedikit informasi di sini ... apakah saya benar-benar dapat mengganti panggilan BeginTransaction()dan RollbackTransaction() dengan melingkupi kode saya menggunakan TransactionScope?

Jika tidak, lalu bagaimana cara TransactionScopemengembalikan transaksi?

mezoid
sumber
Saya belum pernah menggunakan NHibernate, tapi mungkin tautan ini akan membantu Anda.
Jika Anda mencari cara yang lebih baik untuk mengelola sesi NHibernate Anda untuk mengelompokkan operasi ke dalam transaksi, Anda mungkin ingin melihat entri blog saya tentang topik tersebut dotnetchris.wordpress.com/2009/01/27/…
Chris Marisic

Jawaban:

107

Pada dasarnya TransactionScope tidak melacak Adapter Anda, yang dilakukannya adalah melacak koneksi database. Ketika Anda membuka koneksi DB, koneksi akan terlihat jika ada transaksi ambien (Lingkup Transaksi) dan jika demikian mendaftar dengannya. Perhatian jika ada lebih dari satu koneksi ke server SQL yang sama ini akan meningkat ke Transaksi Terdistribusi.

Apa yang terjadi karena Anda menggunakan blok using yang Anda pastikan buang akan dipanggil bahkan jika terjadi pengecualian. Jadi jika buang dipanggil sebelum txScope.Complete () TransactionScope akan memberi tahu koneksi untuk mengembalikan transaksinya (atau DTC).

JoshBerke
sumber
10
TransactionScope tidak melacak apa pun kecuali Transaksi saat ini di utas, dan memodifikasinya jika perlu berdasarkan model (memerlukan, membutuhkan yang baru, dll, dll). Transaksi hanya memberi tahu apa pun yang ada di dalamnya, bukan hanya koneksi database.
casperOne
1
Menurut saya ini tidak sepenuhnya benar. Saya melakukan jejak parsial dari kode sumber TransactionScope dan dan saya juga melihat msdn.microsoft.com/en-us/library/ms172152(v=vs.90).aspx ini yang mengatakan "Jika itu tidak membuat transaksi, komit terjadi setiap kali Commit dipanggil oleh pemilik objek CommittableTransaction. Pada saat itu, Manajer Transaksi memanggil manajer sumber daya dan memberi tahu mereka untuk melakukan atau membatalkan, berdasarkan apakah metode Lengkap dipanggil pada objek TransactionScope. " Jejak sumber juga menunjukkan perilaku ini.
pengguna44298
Saya menemukan SO Q&A ini berguna: IEnlistmentNotification
mungflesh
Masih belum jelas bagiku. Tampaknya objek dengan metode yang dipanggil dalam lingkup transaksi harus bekerja sama dengan mekanisme Transaksi. Mereka harus mencari pemberitahuan Commit / Rollback oleh sistem, dan dapat melakukan rollback sendiri karena merekalah yang melakukan rollback ketika diperlukan (jika penghapusan file dilakukan, jelas kita tidak dapat secara ajaib mengembalikannya kecuali kita mengambilnya. beberapa tindakan pencegahan). Tampaknya operasi server SQL juga kooperatif. Tetapi apakah ada objek kerja sama lain di .Net? Dan bagaimana cara menulis kelas yang kooperatif? Dokumentasi?
menit
54

The TransactionScopekelas bekerja dengan Transactionkelas , yang merupakan benang-spesifik.

Saat TransactionScopedibuat, ia memeriksa untuk melihat apakah ada Transactionuntuk utas; jika ada maka ia menggunakan itu, jika tidak, ia membuat yang baru dan mendorongnya ke tumpukan.

Jika menggunakan yang sudah ada, maka itu hanya menambah penghitung untuk rilis (karena Anda harus memanggilnya Dispose). Pada rilis terakhir, jika Transactionbelum dilakukan, itu akan memutar kembali semua pekerjaan.

Adapun mengapa kelas tampaknya secara ajaib mengetahui tentang transaksi, yang tersisa sebagai detail implementasi untuk kelas-kelas yang ingin bekerja dengan model ini.

Saat Anda membuat instance deptAdapterand emptAdapter, mereka memeriksa untuk melihat apakah ada transaksi saat ini di thread ( Currentproperti statis di Transactionkelas). Jika ada, maka ia mendaftar sendiri dengan Transaction, untuk mengambil bagian dalam urutan commit / rollback (yang Transactionmengontrol, dan mungkin menyebar ke berbagai koordinator transaksi, seperti kernel, didistribusikan, dll.).

casperOne
sumber
4
Bagaimana cara kerjanya dengan SqlConnection yang dibuat dalam lingkup? Apakah kelas SqlConnection secara internal menggunakan kelas Transaksi yang pada gilirannya mendaftar dengan TransactionScope? Atau apakah itu langsung mendaftar ke TLS?
Kakira