วิธีที่สะอาดที่สุดในการใช้ BeginTransaction โดยใช้ try catch

Jan 27 2021

จนถึงตอนนี้ฉันใช้สองบล็อก try catch สำหรับการค้นหาของฉัน อันแรกจะเกิดข้อผิดพลาดหากไม่สามารถสร้างการเชื่อมต่อได้ อันที่สองตรวจสอบว่าSqlCommandดำเนินการสำเร็จหรือไม่ เช่นเดียวกับตัวอย่างด้านล่าง

try
{
  using(varconnection=newSqlConnection())
  using(varcmd=newSqlCommand())
  {
  
    connection.Open();
    var transaction=connection.BeginTransaction();
    cmd.Connection=connection;
    cmd.Transaction=transaction;

    try
    {
     cmd.CommandText="InsertintoCustomers(Name)values('Dimitri')";
     cmd.ExecuteNonQuery();

     cmd.CommandText="InsertintoCustomers(Name)values('George')";
     cmd.ExecuteNonQuery();

     transaction.Commit();
   }
   catch
   {
     try{transaction.Rollback();}catch{}
   }
  }
}
catch
{

}

ฉันพบตัวอย่างที่สองที่ดูชัดเจนมากขึ้นสำหรับฉัน

SqlTransactiontransaction=null;
using(varconnection=newSqlConnection())
using(varcmd=newSqlCommand())
{
   try
   {
   connection.Open();
   transaction=connection.BeginTransaction();
   cmd.Connection=connection;
   cmd.Transaction=transaction;

   cmd.CommandText="InsertintoCustomers(Name)values('Dimitri')";
   cmd.ExecuteNonQuery();

   cmd.CommandText="InsertintoCustomers(Name)values('George')";
   cmd.ExecuteNonQuery();

   transaction.Commit();
   transaction.Dispose();
   transaction=null;
}
catch
{
   if(transaction!=null)
   {
      try{transaction.Rollback();}catch{}
   }
 }
}

ทั้งสองได้ผลเหมือนกันหรือไม่? ชอบอันไหนมากกว่ากัน?

คำตอบ

2 Charlieface Jan 28 2021 at 00:18

ทั้งสองวิธีนี้ไม่ดี พวกเขาฟุ่มเฟื่อยเกินไป

วิธีที่ดีที่สุดคือใส่Transactiona ด้วยusingเช่นกันเราควรใช้พารามิเตอร์สำหรับแบบสอบถาม:

using(var connection = new SqlConnection(connString))
using(var cmd = new SqlCommand("Insert into Customers (Name) values (@Name));"))
{
    var param = cmd.Parameters.Add("@Name", SqlDbType.VarChar, insert_column_length_here);
    connection.Open();
    using(var transaction = connection.BeginTransaction())
    {
        cmd.Transaction = transaction;
        param.Value = "Dimitri";
        cmd.ExecuteNonQuery();

        param.Value = "George";
        cmd.ExecuteNonQuery();

        transaction.Commit();
    }
}

เราจะเห็นว่าการกำจัดวัตถุการทำธุรกรรมจะย้อนกลับโดยอัตโนมัติหากไม่ได้มุ่งมั่นแล้วโดยดูที่รหัสที่มา ดังนั้นusingจะทำความสะอาดทุกอย่าง

หากคุณจำเป็นต้องจับเพื่อแสดงข้อความถึงผู้ใช้ให้ทำนอกรหัสเช่นใส่try/catchสิ่งทั้งหมด อย่าทำรหัสการล้างข้อมูลด้วยตัวคุณเอง