2011-04-06 41 views
15

Giải pháp cuối cùng:

Kết nối đã được thêm vào nhóm kết nối. Vì vậy, tôi đóng nó, nhưng nó vẫn còn thể chất mở. Với tham số ConnectionString "Pooling = false" hoặc các phương thức tĩnh MySqlConnection.ClearPool (kết nối) và MySqlConnection.ClearAllPools, vấn đề có thể tránh được. Lưu ý rằng vấn đề là, rằng kết nối vẫn còn sống khi tôi đóng ứng dụng. Mặc dù tôi đã đóng nó. Vì vậy, hoặc là tôi không sử dụng kết nối tổng hợp ở tất cả hoặc tôi xóa các hồ bơi cụ thể trước khi đóng kết nối và vấn đề được giải quyết. Tôi sẽ dành thời gian để tìm ra giải pháp tốt nhất trong trường hợp của tôi là gì.Sử dụng MySQLConnection trong C# không đóng đúng

Nhờ tất cả những ai đã trả lời! Nó giúp tôi hiểu các khái niệm về C# tốt hơn và tôi đã học được rất nhiều từ đầu vào hữu ích. :)

===

Vấn đề gốc:

tôi đã tìm kiếm một thời gian bây giờ và chưa tìm ra giải pháp cho vấn đề của tôi: Tôi mới đến C# và cố gắng viết một lớp để làm cho MySql Connections dễ dàng hơn. Vấn đề của tôi là, sau khi tôi mở một kết nối và đóng nó lại. Nó vẫn mở trong Database và bị hủy bỏ.

Tôi đang sử dụng câu lệnh 'đang sử dụng', tất nhiên, nhưng kết nối vẫn mở và bị hủy sau khi tôi thoát khỏi chương trình.

Đây là những gì mã của tôi trông giống như:

using (DatabaseManager db = new DatabaseManager()) 
{ 
using (MySqlDataReader result = db.DataReader("SELECT * FROM module WHERE Active=1 ORDER BY Sequence ASC")) 
{ 
    foreach (MySqlDataReader result in db.DataReader("SELECT * FROM module WHERE Active=1 ORDER BY Sequence ASC")) 
    { 
     //Do stuff here 
    } 
} 
} 

Người quản lý lớp học Cơ sở dữ liệu mở kết nối và đóng nó khi xử lý:

public DatabaseManager() 
{ 
    this.connectionString = new MySqlConnectionStringBuilder("Server=localhost;Database=businessplan;Uid=root;"); 
    connect(); 
} 
private bool connect() 
{ 
    bool returnValue = true; 
    connection = new MySqlConnection(connectionString.GetConnectionString(false)); 
    connection.Open(); 
} 

public void Dispose() 
{ 
    Dispose(true); 
} 

public void Dispose(bool disposing) 
{ 
    if (disposing) 
    { 
     if (connection.State == System.Data.ConnectionState.Open) 
     { 
      connection.Close(); 
      connection.Dispose(); 
     } 
    } 
    //GC.SuppressFinalize(this);//Updated 
} 
//Updated 
//~DatabaseManager() 
//{ 
// Dispose(false); 
//} 

Vì vậy, tôi đã kiểm tra nó trong trình gỡ lỗi và Dispose () -method được gọi và thực hiện một cách chính xác. Tôi đang thiếu gì? Có điều gì tôi đã làm sai hoặc hiểu lầm?

Mọi trợ giúp đều được đánh giá cao!

Greetings, Simon

PS: Chỉ trong trường hợp, DataReader() - Phương pháp (phiên bản cập nhật):

public IEnumerable<IDataReader> DataReader(String query) 
    { 
     using (MySqlCommand com = new MySqlCommand()) 
     { 
      com.Connection = connection; 
      com.CommandText = query; 
      using (MySqlDataReader result = com.ExecuteReader(System.Data.CommandBehavior.CloseConnection)) 
      { 
       while (result.Read()) 
       { 
        yield return (IDataReader)result; 
       } 
      } 
     } 
    } 

Ok, tôi cố gắng sử dụng yield return:

foreach (MySqlDataReader result in db.DataReader("SELECT * FROM module WHERE Active=1 ORDER BY Sequence ASC")) 
{ 
    //... 
} 

Và tôi đã thay đổi phương thức DataReader:

public IEnumerable<IDataReader> DataReader(String query) 
    { 
     using (MySqlCommand com = new MySqlCommand()) 
     { 
      com.Connection = connection; 
      com.CommandText = query; 
      using (MySqlDataReader result = com.ExecuteReader()) 
      { 
       while (result.Read()) 
       { 
        yield return (IDataReader)result; 
       } 
      } 
     } 
    } 

Nó hoạt động theo cách tôi có thể truy xuất dữ liệu, nhưng tôi vẫn gặp sự cố tương tự: Kết nối không được đóng đúng cách. :(

+0

Vì bạn không có bất kỳ tài nguyên không được quản lý nào, bạn không cần trình hoàn thiện. – SLaks

+0

Đúng vậy. Nhưng nó không làm tổn thương hiện tại, phải không? Đúng nếu tôi nhầm. Mục tiêu chính là đóng các kết nối không sử dụng ngay khi chúng không còn cần thiết nữa. Mô hình này dường như là một cách dễ dàng để đạt được mục tiêu này. Tôi đã thực hiện nó theo cách được thể hiện trong nhiều ví dụ trên web. Cuối cùng tôi sẽ thay đổi nó để loại bỏ mã dư thừa. – Skalli

+1

Đó là một hit hiệu suất, nhưng nếu không, không. – SLaks

Trả lời

15

Im chắc chắn về MySqlConnection nhưng máy chủ sql truy cập phần sử dụng kết nối tổng hợp và không đóng khi bạn gọi gần thay vì nó đặt nó trong hồ bơi kết nối!

Chỉnh sửa: Đảm bảo bạn đã bỏ đối tượng Reader, Command và Connection!

Chỉnh sửa: Solved với ConnectionString Parameter "Pooling = false" hoặc các phương pháp MySqlConnection.ClearPool tĩnh (kết nối) và MySqlConnection.ClearAllPools()

+0

Hiện tại tôi đang sử dụng hướng dẫn sử dụng cho các mục này. Xem [link] (http://stackoverflow.com/questions/5567097/using-mysqlconnection-in-c-does-not-close-properly/5567722#5567722). Tuy nhiên nó không sử dụng. – Skalli

+1

Bài đăng này thực sự có câu trả lời tôi đang tìm kiếm, nhưng tôi đã không nhận ra nó, bởi vì tôi không quen với cách thức hoạt động của Connection Pooling. Bây giờ tôi hiểu và tôi đã giải quyết được vấn đề. Vì vậy, cảm ơn rất nhiều @Petoj. – Skalli

+0

không có vấn đề gì vui lòng trợ giúp! – Peter

5

Bạn cũng cần phải bao bọc Lệnh và Trình quản lý dữ liệu trong các câu lệnh using.

+1

Vâng, nhưng làm thế nào? Nếu tôi bọc MySqlDataReader trong một khối sử dụng, nó chỉ có sẵn cục bộ. Phương thức DataReader trả về đối tượng cho một khối sử dụng. Tôi giả định rằng điều này sẽ xử lý MySqlDataReader-Object ở cuối khối sử dụng: using (MySqlDataReader result = db.DataReader (...) – Skalli

+0

Anh ta sẽ không thể bọc nó vì anh ta trả về MySqlDataReader - Tôi không nghĩ rằng bạn nên xử lý MySqlCommand cho đến khi bạn đã kết thúc với MySqlDataReader.Ông nên có lẽ nhìn vào một lợi nhuận mang lại để biến điều này trong một đóng cửa –

+0

Bạn đang phải.Bạn có thể xử lý sự kiện 'Disposed' của người đọc: 'reader.Disposed + = delegate {com.Dispose();}' – SLaks

-1

Có xem xét sử dụng một cái gì đó như thế này:

private static IEnumerable<IDataRecord> SqlRetrieve(
    string ConnectionString, 
    string StoredProcName, 
    Action<SqlCommand> AddParameters) 
{ 
    using (var cn = new SqlConnection(ConnectionString)) 
    using (var cmd = new SqlCommand(StoredProcName, cn)) 
    { 
     cn.Open(); 
     cmd.CommandType = CommandType.StoredProcedure; 

     if (AddParameters != null) 
     { 
      AddParameters(cmd); 
     } 

     using (var rdr = cmd.ExecuteReader(CommandBehavior.CloseConnection)) 
     { 
      while (rdr.Read()) 
       yield return rdr; 
     } 
    } 
} 
+0

Tôi sẽ xem xét nó. Có vẻ khá thú vị. Chưa từng thấy lợi nhuận trước đây. – Skalli

+0

@ user694856 http://stackoverflow.com/ question/850065/return-datareader-from-datalayer-in-using-statement –

+0

Tôi đã thử sử dụng nó, xem bài đăng của tôi: [link] (http://stackoverflow.com/questions/5567097/using-mysqlconnection-in- c-không-không-đúng-đúng/5567722 # 5567722) – Skalli

2

Theo các tài liệu mysql, các MySqlConnection không đóng cửa khi nó đi ra khỏi phạm vi. Vì vậy, bạn không được sử dụng nó bên trong một sử dụng.

Trích dẫn ... "Nếu MySqlConnection nằm ngoài phạm vi, nó không bị đóng. Do đó, bạn phải đóng kết nối rõ ràng bằng cách gọi MySqlConnection.Close hoặc MySqlConnection.Dispose."

+2

Sử dụng nên gọi gần và vứt bỏ khi vật thể nằm ngoài phạm vi. Nó giống như sử dụng khối try try và đóng và vứt nó vào khối cuối cùng. – Skalli

+1

@Skalli là chính xác. Để lại phạm vi của một tuyên bố sử dụng không giống như mất phạm vi theo nghĩa ngôn ngữ. Một câu lệnh sử dụng sẽ gọi Close. –

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