TransactionScope ย้อนธุรกรรมอย่างไร


101

ฉันกำลังเขียนการทดสอบการรวมซึ่งฉันจะแทรกวัตถุจำนวนหนึ่งลงในฐานข้อมูลจากนั้นตรวจสอบเพื่อให้แน่ใจว่าวิธีการของฉันดึงวัตถุเหล่านั้นมาหรือไม่

การเชื่อมต่อกับฐานข้อมูลของฉันคือผ่าน NHibernate ... และวิธีการสร้างการทดสอบตามปกติของฉันคือการทำสิ่งต่อไปนี้:

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();

อย่างไรก็ตามฉันเพิ่งค้นพบเกี่ยวกับTransactionScopeซึ่งเห็นได้ชัดว่าสามารถใช้เพื่อจุดประสงค์นี้ ...

บางโค้ดตัวอย่างที่ฉันได้พบจะเป็นดังนี้:

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;

}

ฉันเชื่อว่าถ้าฉันไม่รวมบรรทัดtxScope.Complete()ที่ข้อมูลที่แทรกจะถูกย้อนกลับ แต่น่าเสียดายที่ฉันไม่เข้าใจว่ามันเป็นไปได้อย่างไร ... txScopeวัตถุจะติดตามdeptAdapterและempAdapterวัตถุและธุรกรรมบนฐานข้อมูลได้อย่างไร

ฉันรู้สึกว่าฉันขาดข้อมูลเล็กน้อยที่นี่ ... ฉันสามารถแทนที่BeginTransaction()และRollbackTransaction() การโทรโดยใช้รหัสของฉันได้TransactionScopeหรือไม่?

ถ้าไม่แล้วTransactionScopeจะย้อนกลับธุรกรรมได้อย่างไร?


ฉันไม่เคยใช้ NHibernate แต่ลิงค์นี้อาจช่วยคุณได้

หากคุณกำลังมองหาวิธีที่ดีกว่าในการจัดการเซสชัน NHibernate ของคุณเพื่อจัดกลุ่มการดำเนินการเป็นธุรกรรมคุณอาจต้องการดูบล็อกโพสต์ของฉันในหัวข้อนั้นdotnetchris.wordpress.com/2009/01/27/…
Chris Marisic

คำตอบ:


109

โดยพื้นฐานแล้ว TransactionScope ไม่ได้ติดตาม Adapter ของคุณสิ่งที่ทำคือติดตามการเชื่อมต่อฐานข้อมูล เมื่อคุณเปิดการเชื่อมต่อฐานข้อมูลการเชื่อมต่อจะดูว่ามีธุรกรรมโดยรอบหรือไม่ (ขอบเขตธุรกรรม) และหากเป็นเช่นนั้นก็เข้าร่วมด้วย ข้อควรระวังหากมีมากกว่าหนึ่งการเชื่อมต่อกับเซิร์ฟเวอร์ SQL เดียวกันสิ่งนี้จะส่งต่อไปยังธุรกรรมแบบกระจาย

สิ่งที่เกิดขึ้นเนื่องจากคุณใช้บล็อกการใช้งานคุณมั่นใจว่าจะถูกเรียกใช้แม้ว่าจะมีข้อยกเว้นเกิดขึ้นก็ตาม ดังนั้นหากเรียกว่า dispose ก่อน txScope.Complete () TransactionScope จะบอกการเชื่อมต่อให้ย้อนกลับธุรกรรมของตน (หรือ DTC)


10
TransactionScope ไม่ได้ติดตามอะไรเลยนอกจากธุรกรรมปัจจุบันบนเธรดและแก้ไขหากจำเป็นต้องเป็นไปตามโมเดล (ต้องใช้ต้องใช้ใหม่ ฯลฯ ฯลฯ ) ธุรกรรมเพียงแค่แจ้งทุกสิ่งที่ขอเข้าร่วมไม่ใช่แค่การเชื่อมต่อฐานข้อมูล
casperOne

1
ฉันคิดว่านี่ไม่เป็นความจริงทั้งหมด ฉันได้ติดตามซอร์สโค้ดบางส่วนของ TransactionScope และฉันยังเห็นmsdn.microsoft.com/en-us/library/ms172152(v=vs.90).aspxนี้ ซึ่งระบุว่า "หากไม่ได้สร้างธุรกรรม การกระทำจะเกิดขึ้นเมื่อใดก็ตามที่เจ้าของวัตถุ Commit เรียกใช้ CommitableTransaction ณ จุดนั้นตัวจัดการธุรกรรมจะเรียกตัวจัดการทรัพยากรและแจ้งให้พวกเขาทำการคอมมิตหรือย้อนกลับโดยขึ้นอยู่กับว่าเมธอด Complete ถูกเรียกบนอ็อบเจ็กต์ TransactionScope หรือไม่ " การติดตามแหล่งที่มายังระบุลักษณะการทำงานนี้
user44298

ฉันพบว่า SO Q&A นี้มีประโยชน์: IEnlistmentNotification
mungflesh

ยังไม่ชัดเจนสำหรับฉัน ดูเหมือนว่าออบเจ็กต์ที่มีวิธีการที่เรียกว่าภายในขอบเขตธุรกรรมจะต้องร่วมมือกับกลไกการทำธุรกรรม พวกเขาต้องมองหาการแจ้งเตือน Commit / Rollback โดยระบบและสามารถย้อนกลับได้เองเนื่องจากเป็นสิ่งที่จะดำเนินการย้อนกลับเมื่อจำเป็น (หากมีการดำเนินการลบไฟล์แน่นอนว่าเราไม่สามารถย้อนกลับได้อย่างน่าอัศจรรย์เว้นแต่เราจะเอา มาตรการป้องกันบางประการ) ดูเหมือนว่าการทำงานของเซิร์ฟเวอร์ SQL จะทำงานร่วมกัน แต่มีวัตถุความร่วมมืออื่น ๆ ใน. Net หรือไม่? และวิธีการเขียนชั้นเรียนที่ร่วมมือกัน? เอกสารประกอบ?
นาทีที่

54

TransactionScopeระดับผลงานที่มีTransactionระดับซึ่งเป็นหัวข้อที่เฉพาะเจาะจง

เมื่อTransactionScopeสร้างขึ้นมันจะตรวจสอบว่ามีTransactionเธรดหรือไม่ หากมีอยู่ก็จะใช้สิ่งนั้นมิฉะนั้นจะสร้างใหม่และผลักดันไปยังสแต็ก

หากใช้อันที่มีอยู่มันก็จะเพิ่มตัวนับสำหรับการเผยแพร่ (เนื่องจากคุณต้องเรียกDisposeใช้) ในรุ่นที่แล้วหากยังTransactionไม่ได้รับการติดตั้งระบบจะย้อนกลับงานทั้งหมด

เหตุใดชั้นเรียนจึงดูเหมือนจะรู้เกี่ยวกับธุรกรรมอย่างน่าอัศจรรย์นั่นคือรายละเอียดการใช้งานสำหรับคลาสเหล่านั้นที่ต้องการทำงานกับโมเดลนี้

เมื่อคุณสร้างอินสแตนซ์ของคุณdeptAdapterและemptAdapterพวกเขาจะตรวจสอบว่ามีธุรกรรมปัจจุบันบนเธรดหรือไม่ ( Currentคุณสมบัติคงที่ในTransactionคลาส) หากมีจะลงทะเบียนตัวเองด้วยTransactionเพื่อมีส่วนร่วมในลำดับการกระทำ / ย้อนกลับ (ซึ่งTransactionควบคุมและอาจนำเสนอไปยังผู้ประสานงานธุรกรรมที่แตกต่างกันเช่นเคอร์เนลแบบกระจาย ฯลฯ )


4
มันทำงานอย่างไรกับ SqlConnection (s) ที่สร้างขึ้นภายในขอบเขต? คลาส SqlConnection ใช้คลาส Transaction ภายในซึ่งจะเข้าร่วมกับ TransactionScope หรือไม่ หรือสมัครเข้า TLS โดยตรง?
Kakira
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.