ฉันต้องการเรียกใช้คำสั่งแทรกหลายรายการในหลายตาราง ฉันใช้ dapper.net ฉันไม่เห็นวิธีจัดการธุรกรรมกับ dapper.net เลย
โปรดแบ่งปันแนวคิดของคุณเกี่ยวกับวิธีใช้ธุรกรรมกับ dapper.net
ฉันต้องการเรียกใช้คำสั่งแทรกหลายรายการในหลายตาราง ฉันใช้ dapper.net ฉันไม่เห็นวิธีจัดการธุรกรรมกับ dapper.net เลย
โปรดแบ่งปันแนวคิดของคุณเกี่ยวกับวิธีใช้ธุรกรรมกับ dapper.net
คำตอบ:
นี่คือข้อมูลโค้ด:
using System.Transactions;
....
using (var transactionScope = new TransactionScope())
{
DoYourDapperWork();
transactionScope.Complete();
}
โปรดทราบว่าคุณจำเป็นต้องเพิ่มการอ้างอิงไปยังSystem.Transactions
แอสเซมบลีเนื่องจากไม่ได้อ้างอิงตามค่าเริ่มต้น
Dispose()
วิธีการ หากComplete()
ยังไม่ถูกเรียกธุรกรรมจะถูกย้อนกลับ
TransctionScope
ใช้บล็อกในกรณีที่คุณเลือกคำตอบนี้
ฉันต้องการใช้วิธีการที่ง่ายกว่าโดยรับธุรกรรมโดยตรงจากการเชื่อมต่อ:
// This called method will get a connection, and open it if it's not yet open.
using (var connection = GetOpenConnection())
using (var transaction = connection.BeginTransaction())
{
connection.Execute(
"INSERT INTO data(Foo, Bar) values (@Foo, @Bar);", listOf5000Items, transaction);
transaction.Commit();
}
.BeginTransaction()
เท่านั้นหรือไม่? หากเป็นเช่นนั้นวิธีการส่วนขยายนี้จะส่งเสริมการใช้ธุรกรรมที่ไม่ถูกต้อง (IMO ควรโยน "ไม่สามารถเปิดธุรกรรมได้หลังจากที่การเชื่อมต่อเปิดอยู่แล้ว")
Execute
ด้วยเนื่องจากจำเป็น
คุณควรจะสามารถใช้ได้TransactionScope
เนื่องจาก Dapper รันเพียงคำสั่ง ADO.NET
using (var scope = new TransactionScope())
{
// open connection
// insert
// insert
scope.Complete();
}
เมื่อพิจารณาว่าตารางทั้งหมดของคุณอยู่ในฐานข้อมูลเดียวฉันไม่เห็นด้วยกับTransactionScope
โซลูชันที่แนะนำในบางคำตอบที่นี่ อ้างถึงนี้คำตอบ
TransactionScope
โดยทั่วไปจะใช้สำหรับธุรกรรมแบบกระจาย ธุรกรรมที่ครอบคลุมฐานข้อมูลที่แตกต่างกันอาจอยู่ในระบบที่ต่างกัน สิ่งนี้ต้องการการกำหนดค่าบางอย่างบนระบบปฏิบัติการและ SQL Server โดยที่สิ่งนี้จะไม่ทำงาน ไม่แนะนำให้ทำเช่นนี้หากแบบสอบถามทั้งหมดของคุณขัดกับฐานข้อมูลอินสแตนซ์เดียว
แต่ด้วยฐานข้อมูลเดียวสิ่งนี้อาจมีประโยชน์เมื่อคุณต้องรวมรหัสในธุรกรรมที่ไม่อยู่ภายใต้การควบคุมของคุณ ด้วยฐานข้อมูลเดียวไม่จำเป็นต้องมีการกำหนดค่าพิเศษเช่นกัน
connection.BeginTransaction
เป็นไวยากรณ์ ADO.NET เพื่อใช้ธุรกรรม (ใน C #, VB.NET ฯลฯ ) กับฐานข้อมูลเดียว สิ่งนี้ใช้ไม่ได้กับหลายฐานข้อมูล
ดังนั้น, connection.BeginTransaction()
เป็นวิธีที่ดีกว่าที่จะไป
แม้จะเป็นวิธีที่ดีในการจัดการการทำธุรกรรมที่จะใช้ UnitOfWork ที่อธิบายไว้ในนี้คำตอบ
TransactionScope
ซึ่งไม่มีประสิทธิภาพสำหรับสิ่งที่ OP ต้องการ ฉันยอมรับว่าTransactionScope
เป็นเครื่องมือที่ดีในหลาย ๆ กรณี แต่ไม่ใช่สิ่งนี้
คำตอบของแดเนียลได้ผลสำหรับฉัน เพื่อความสมบูรณ์นี่คือตัวอย่างข้อมูลที่แสดงการกระทำและการย้อนกลับโดยใช้ขอบเขตธุรกรรมและ dapper:
using System.Transactions;
// _sqlConnection has been opened elsewhere in preceeding code
using (var transactionScope = new TransactionScope())
{
try
{
long result = _sqlConnection.ExecuteScalar<long>(sqlString, new {Param1 = 1, Param2 = "string"});
transactionScope.Complete();
}
catch (Exception exception)
{
// Logger initialized elsewhere in code
_logger.Error(exception, $"Error encountered whilst executing SQL: {sqlString}, Message: {exception.Message}")
// re-throw to let the caller know
throw;
}
} // This is where Dispose is called
Dispose
วิธีใดเรียกว่าแรกหรือที่สองเพียงแค่เรียกว่าสองครั้ง สำหรับประเด็นที่ว่า "การโทรทิ้งครั้งที่สองไม่เป็นอันตราย" นั่นเป็นข้อสันนิษฐานที่สำคัญ ฉันได้เรียนรู้ว่าเอกสารและการใช้งานจริงมักไม่เห็นด้วย แต่ถ้าคุณต้องการคำพูดของ Microsoft: msdn.microsoft.com/en-us/library/…