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 txScope
objek melacak deptAdapter
dan empAdapter
objek 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 TransactionScope
mengembalikan transaksi?
Jawaban:
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).
sumber
The
TransactionScope
kelas bekerja denganTransaction
kelas , yang merupakan benang-spesifik.Saat
TransactionScope
dibuat, ia memeriksa untuk melihat apakah adaTransaction
untuk 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, jikaTransaction
belum 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
deptAdapter
andemptAdapter
, mereka memeriksa untuk melihat apakah ada transaksi saat ini di thread (Current
properti statis diTransaction
kelas). Jika ada, maka ia mendaftar sendiri denganTransaction
, untuk mengambil bagian dalam urutan commit / rollback (yangTransaction
mengontrol, dan mungkin menyebar ke berbagai koordinator transaksi, seperti kernel, didistribusikan, dll.).sumber