วิธีการตรวจจับข้อยกเว้นการหมดเวลาของ SQLServer


117

ฉันจำเป็นต้องจับข้อยกเว้นการหมดเวลาของเซิร์ฟเวอร์ SQL โดยเฉพาะเพื่อให้สามารถจัดการได้แตกต่างกัน ฉันรู้ว่าฉันสามารถจับ SqlException แล้วตรวจสอบว่าสตริงข้อความมี "หมดเวลา" หรือไม่ แต่สงสัยว่ามีวิธีที่ดีกว่านี้หรือไม่

try
{
    //some code
}
catch (SqlException ex)
{

    if (ex.Message.Contains("Timeout"))
    {
         //handle timeout
    }
    else
    {
         throw;
    }
}

คุณกำลังมองหา ConnectionTimeout หรือ CommandTimeout นั่นคือคุณคาดว่าการเชื่อมต่อจะล้มเหลวหรือคำสั่งที่เรียกใช้งานล้มเหลวหรือไม่?
edosoft

ฉันกำลังมองหา CommandTimeout ซึ่งตั้งไว้เป็นค่าเริ่มต้น 30 วินาทีฉันคิดว่า
brodie

คำตอบ:


157

ในการตรวจสอบการหมดเวลาฉันเชื่อว่าคุณตรวจสอบค่าของ ex.Number ถ้าเป็น -2 แสดงว่าคุณมีสถานการณ์หมดเวลา

-2 คือรหัสข้อผิดพลาดสำหรับการหมดเวลาส่งคืนจาก DBNETLIB ไดรเวอร์ MDAC สำหรับ SQL Server สิ่งนี้สามารถเห็นได้โดยการดาวน์โหลดตัวสะท้อนแสงและดูที่ System.Data.SqlClient.TdsEnums สำหรับ TIMEOUT_EXPIRED

รหัสของคุณจะอ่าน:

if (ex.Number == -2)
{
     //handle timeout
}

รหัสเพื่อแสดงความล้มเหลว:

try
{
    SqlConnection sql = new SqlConnection(@"Network Library=DBMSSOCN;Data Source=YourServer,1433;Initial Catalog=YourDB;Integrated Security=SSPI;");
    sql.Open();

    SqlCommand cmd = sql.CreateCommand();
    cmd.CommandText = "DECLARE @i int WHILE EXISTS (SELECT 1 from sysobjects) BEGIN SELECT @i = 1 END";
    cmd.ExecuteNonQuery(); // This line will timeout.

    cmd.Dispose();
    sql.Close();
}
catch (SqlException ex)
{
    if (ex.Number == -2) {
        Console.WriteLine ("Timeout occurred");
    }
}

ใช่นั่นคือสิ่งที่ฉันกำลังทำอยู่ในขณะนี้ แต่มันไม่ได้เป็นการตรวจสอบที่สวยงามมากนักสำหรับ -2
brodie

12
ดาวน์โหลด Red Gate's Reflector และค้นหา TIMEOUT_EXPIRED มันอาศัยอยู่ใน System.Data.SqlClient.TdsEnums และค่าของมันคือ -2 : o)
โจนาธาน

2
สำหรับผู้ที่ไม่มีสิทธิ์เข้าถึง Reflector: link
ankitk

4
@brodie นั่นเป็นเหตุผลที่คุณควรสร้างค่าคงที่และคุณสามารถอธิบายได้ว่าค่า "เวทมนตร์" มาจากไหนในความคิดเห็นเกี่ยวกับค่าคงที่
Jason L.

18

ที่นี่: http://www.tech-archive.net/Archive/DotNet/microsoft.public.dotnet.framework.adonet/2006-10/msg00064.html

คุณสามารถอ่านได้ด้วยว่าThomas Weingartnerเขียน:

หมดเวลา: SqlException.Number == -2 (นี่คือรหัสข้อผิดพลาด ADO.NET) ข้อผิดพลาด
ทั่วไปของเครือข่าย: SqlException.Number == 11 การ
หยุดชะงัก: SqlException.Number == 1205 (นี่คือรหัสข้อผิดพลาดของ SQL Server)

...

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



0

ค่าสำหรับคุณสมบัติ SqlException.ErrorCode คืออะไร? คุณสามารถทำงานกับสิ่งนั้นได้หรือไม่?

เมื่อมีการหมดเวลาก็อาจจะมีมูลค่าการตรวจสอบรหัสสำหรับ-2146232060

ฉันจะตั้งค่านี้เป็นค่าคงที่ในรหัสข้อมูลของคุณ


2
เมื่อดูเอกสารสำหรับ ErrorCode สำหรับฉันแล้วดูเหมือนว่ากำลังรายงานข้อผิดพลาดระดับการทำงานร่วมกัน ดังนั้นจึงอาจมากกว่าในระดับของข้อผิดพลาด COM หรือผู้ให้บริการพบข้อยกเว้น (โดยทั่วไป) แทนที่จะเป็นข้อผิดพลาดเฉพาะที่เกี่ยวข้องกับสิ่งที่คุณกำลังทำ
Eric Tuttleman

@Eric ถูกต้อง - นั่นคือรหัส HRESULT สำหรับชนิด SqlException ไม่ใช่สำหรับแหล่งที่มาของข้อยกเว้น
codekaizen

0

ฉันไม่แน่ใจ แต่เมื่อเราดำเนินการหมดเวลาหรือหมดเวลาคำสั่งไคลเอนต์จะส่ง "ABORT" ไปยัง SQL Server จากนั้นก็ละทิ้งการประมวลผลแบบสอบถาม ไม่มีการย้อนธุรกรรมไม่มีการล็อกใด ๆ เพื่อแก้ปัญหานี้ฉันลบธุรกรรมใน Stored-procedure และใช้ SQL Transaction ใน. Net Code ของฉันเพื่อจัดการ sqlException


-2

เมื่อลูกค้าส่ง ABORT จะไม่มีการย้อนธุรกรรม เพื่อหลีกเลี่ยงพฤติกรรมนี้เราต้องใช้ SET_XACT_ABORT ON https://docs.microsoft.com/en-us/sql/t-sql/statements/set-xact-abort-transact-sql?view=sql-server-ver15


1
ไม่ตอบคำถามซึ่งเป็นวิธีจับคำสั่งหมดเวลาในรหัส c #
Jonathan
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.