2016-05-25 14 views
10

Tôi có đoạn mã sau:Khi nào là DbConnection.StateChange được gọi?

class Program 
{ 
    static void Main() 
    { 
     var connection = new SqlConnection("myConnectionString"); 
     connection.Open(); 
     connection.StateChange += HandleSqlConnectionDrop; 
     Console.WriteLine("Hi"); 
     Console.ReadLine(); 
    } 

    private static void HandleSqlConnectionDrop(object connection, StateChangeEventArgs args) 
    { 
     Console.WriteLine("DB change detected"); 
    } 
} 

tôi bắt đầu mã trên trong khi dụ SQL máy chủ đang chạy. Sau đó, tôi tiếp tục thực hiện

SHUTDOWN WITH NOWAIT; 

trên cá thể máy chủ sql mà chương trình được kết nối. Sau đó tôi quan sát dịch vụ máy chủ SQL dừng lại. Tuy nhiên, tôi không bao giờ thấy thông báo "DB phát hiện thay đổi" trong đầu ra. Tại sao điều này?

Ngoài: Tôi sẽ thấy trình xử lý StateChange được gọi nếu sau đó tôi cố gắng thực hiện thao tác trên kết nối SQL, nhưng chưa bao giờ trước khi thực hiện. Có cách nào hành vi này có thể thay đổi không?

+0

"Tôi sẽ thấy trình xử lý StateChange được gọi nếu sau đó tôi cố gắng thực hiện một thao tác trên kết nối SQL" - Trong thực tế, bạn trả lời câu hỏi của mình. Đối tượng kết nối không ping server và chỉ kiểm tra trạng thái khi cần. Đặt 'connection.Open()' sau '.StateChange + = ...' để thấy nó hoạt động. –

+0

@AlexKudryashev Không nên có một số loại giữ sống giữa khách hàng SQL và máy chủ SQL? Sự hiểu biết của tôi là các đối tượng SqlConnection nên ánh xạ một phiên một với các phiên máy chủ SQL. Nếu máy chủ giết phiên, có cách nào để tôi có thể có thông tin đó được chuyển tới mã của tôi không? –

+0

bạn có thể thử thăm dò máy chủ bằng thứ gì đó vô hại như 'select 1' –

Trả lời

3

Sự kiện StateChange có nghĩa là trạng thái của kết nối, chứ không phải trường hợp của máy chủ cơ sở dữ liệu. Để nhận trạng thái của máy chủ cơ sở dữ liệu,

Sự kiện StateChange xảy ra khi trạng thái của sự kiện thay đổi từ đóng để mở hoặc mở để đóng.

Từ MSDN: https://msdn.microsoft.com/en-us/library/system.data.common.dbconnection.statechange(v=vs.110).aspx

Nếu bạn đang đi để cuộn màn hình của riêng bạn cho các cơ sở dữ liệu, sau đó bạn có thể xem xét sử dụng một phương pháp mà trả về true/false nếu kết nối có sẵn và ping phương pháp trên một lịch trình. Bạn thậm chí có thể bọc một phương pháp để làm điều này trong một vòng lặp vô tận lặp đi lặp lại sau một khoảng thời gian và nâng cao sự kiện riêng của nó khi "trạng thái" này thực sự thay đổi sau đó.

Dưới đây là một phương pháp nhanh chóng từ một câu trả lời SO đó là một phương pháp đơn giản:

/// <summary> 
/// Test that the server is connected 
/// </summary> 
/// <param name="connectionString">The connection string</param> 
/// <returns>true if the connection is opened</returns> 
private static bool IsServerConnected(string connectionString) 
{ 
    using (SqlConnection connection = new SqlConnection(connectionString)) 
    { 
     try 
     { 
      connection.Open(); 
      return true; 
     } 
     catch (SqlException) 
     { 
      return false; 
     } 
    } 
} 

Nguồn: https://stackoverflow.com/a/9943871/4154421

+0

"Sự kiện StateChange có nghĩa là cho trạng thái kết nối, không phải là trường hợp của máy chủ cơ sở dữ liệu." -> Nhưng nếu trạng thái của máy chủ thay đổi, trạng thái kết nối cũng sẽ thay đổi (tức là trở thành "không còn chức năng"). –

+0

Nhưng kết nối sẽ không phát hiện sự thay đổi trạng thái của máy chủ cơ sở dữ liệu trừ khi bạn thực sự truy vấn chống lại máy chủ, đó là lý do tại sao bạn nên có một trình bao bọc như được lưu ý trong câu trả lời để bạn có một cách đáng tin cậy để xác định các thay đổi trạng thái thực sự và không chỉ ở lớp ứng dụng của bạn. –

8

Khi được DbConnection.StateChange gọi là?

Bạn có thể tìm hiểu bằng cách xem mã nguồn tham chiếu của Microsoft.

Sự kiện StateChange được nâng lên bởi hàm DbConnection.OnStateChange. Tìm kiếm tham chiếu đến hàm này chỉ tạo ra một vài trường hợp:

Thứ nhất, trong lớp SqlConnection, OnStateChange chỉ được gọi trong phương thức Close.

Sau đó, trong tệp DbConnectionHelper.cs, có một lớp được gọi là DBCONNECTIONOBJECT. Có vẻ như nó được sử dụng cho tất cả các lớp học được sử dụng cho một số shenanigans xây dựng thời gian. Vì vậy, bạn có thể coi nó là một phần của SqlConnection. Trong mọi trường hợp, nó chỉ gọi OnStateChange chỉ từ trong hàm SetInnerConnectionEvent.

Theo như tôi có thể nói (phần vô nghĩa của lớp làm cho nó khó khăn), SqlConnection.SetInnerConnectionEvent chỉ được gọi từ SqlConnectionFactory.SetInnerConnectionEvent.Và rằng được gọi là từ:

Vì vậy, trong bản tóm tắt - sự kiện này chỉ được huy động để đáp ứng với những hành động phía máy khách - không có không dường như là bất kỳ cuộc thăm dò nào của trạng thái kết nối được tích hợp vào SQLConnection.

Có cách nào để thay đổi hành vi này không?

Nhìn vào mã nguồn, tôi không thể nhìn thấy mã nguồn. Như những người khác đã gợi ý, bạn có thể thực hiện bỏ phiếu của riêng bạn, tất nhiên.

Các vấn đề liên quan