2010-10-28 19 views
8

Tôi nhận được lỗi "Giao dịch mới không được phép vì có các luồng khác đang chạy" trong một ứng dụng tôi đang làm việc. Nó đã phát sinh trong quá trình tái cấu trúc và đặc biệt trong quá trình tạo ra một bộ thử nghiệm.Có cách nào để phát hiện người đọc mở trên SqlConnection không?

Tôi nhận thấy từ việc nhìn xung quanh điều đó có nghĩa là tôi có thể có trình đọc dữ liệu vẫn mở khi tôi tạo giao dịch, tuy nhiên đó là ứng dụng phức tạp và không rõ vấn đề của tôi ở đâu. Vì vậy, tôi muốn có thể tìm ra những độc giả nào được kết nối với SqlConnection trong câu hỏi.

Lý tưởng nhất là tôi muốn có thể thêm đồng hồ trong Visual Studio và sau đó từng bước trong chế độ gỡ lỗi để xem thời điểm số lượng trình đọc được kết nối thay đổi.

Có cách nào để thực hiện việc này không? Tôi đang làm việc trong C#.

Xin cảm ơn trước.

Martin

Trả lời

7

Phew! Tôi biết nhiều hơn về Reflection ngay bây giờ!

Đối với bất kỳ ai khác tìm câu trả lời cho điều này, đây là phương thức trả về số lượng trình đọc dữ liệu trên SqlConnection.

public static int CountConnectedReaders(SqlConnection conn) 
{ 
    int readers = 0; 
    Type t = conn.GetType(); 
    MemberInfo[] minf = t.GetMembers(BindingFlags.NonPublic | BindingFlags.Instance); 
    for (int i = 0; i < minf.Length; i++) 
    { 
    if (minf[i].Name == "get_InnerConnection") 
    {      
     MethodInfo methinf = (MethodInfo)minf[i]; 

     object result = methinf.Invoke(conn, new object[0]); 

     PropertyInfo[] pinfs = result.GetType().GetProperties(BindingFlags.NonPublic | BindingFlags.Instance); 
     foreach (PropertyInfo pinf in pinfs) 
     { 
     if (pinf.PropertyType.Name == "DbReferenceCollection") 
     { 
      object dbrc = pinf.GetValue(result, new object[0]); 
      if (dbrc == null) readers = 0; 
      else 
      { 
      MemberInfo[] dbrcInfs = dbrc.GetType().GetMembers(BindingFlags.NonPublic | BindingFlags.Instance); 
      foreach (MemberInfo dbrcInf in dbrcInfs) 
      { 
       if (dbrcInf.Name == "_dataReaderCount") 
       { 
       FieldInfo finf = (FieldInfo)dbrcInf; 
       readers = (Int32) finf.GetValue(dbrc); 
       } 
      } 
      } 
     } 
     } 
    } 
    } 

    return readers; 
} 

Điều thú vị là, sử dụng điều này trong mã vấn đề của tôi cho thấy không có độc giả dữ liệu mở về kết nối khi tôi nhận được "giao dịch mới là không được phép vì có chủ đề khác chạy" lỗi để trở lại bàn vẽ (hoặc ít nhất một câu hỏi SO khác) với điều đó.

+0

Ồ, một người nào đó đã bỏ phiếu cho câu trả lời này (tôi mất nhiều giờ để làm việc) dưới dạng "không hữu ích". Tôi rất muốn biết tại sao. – marsbard

+0

Idiots ở mọi nơi. Nice tìm thấy - Tôi biết không có cách nào để có được điều đó từ giao diện tài liệu, nhưng rõ ràng là kết nối cần thiết để có một tài liệu tham khảo một nơi nào đó. Vâng, ít nhất là một số độc giả mở. – TomTom

+0

Thực hiện tốt. Đã bỏ phiếu +1. – TomTom

1

Bạn có thể tìm thấy điều này thread quan tâm.

Chỉnh sửa: Có vẻ như họ đã nhận được DbConnectionInternal với Reflector và phiên bản miễn phí có sẵn. Đối với sự phản ánh, nó không phải là quá phức tạp thực sự. Có một cái nhìn tổng quan về MSDN.

Chỉnh sửa2: Chỉ cần nhận ra rằng bạn đã tìm ra. Tuyệt quá. :) Tôi sẽ để lại bản chỉnh sửa trong trường hợp ai đó khác muốn biết thêm thông tin.

+0

Đó là một chủ đề thú vị và phù hợp. Tôi là một chút ra khỏi chiều sâu của tôi khi cố gắng sử dụng Reflection mặc dù :) Ngoài ra tôi không thể tìm thấy DBConnectionInternal khi nhấp qua người trợ giúp IntelliSense trong chế độ gỡ lỗi. – marsbard

+0

Cảm ơn bạn đã liên kết đến Reflector. Có vẻ tốt. – marsbard

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