2011-04-06 5 views
15

최종 솔루션 :

연결이 연결 풀에 추가되었습니다. 그래서 저는 그것을 닫았지만 여전히 육체적으로 열려 있습니다. ConnectionString 매개 변수 "풀링 = 거짓"또는 정적 메서드 인 MySqlConnection.ClearPool (연결) 및 MySqlConnection.ClearAllPools을 사용하면 문제를 피할 수 있습니다. 문제는 응용 프로그램을 닫을 때 연결이 여전히 살아 있다는 것입니다. 비록 내가 그것을 닫았다. 따라서 연결 풀링을 전혀 사용하지 않거나 연결을 종료하기 전에 특정 풀을 지우고 문제가 해결됩니다. 제 경우에 가장 좋은 해결책이 무엇인지 알아내는 데 시간을 할애 할 것입니다.C#에서 MySQLConnection을 사용하면 제대로 닫히지 않습니다.

답장을 보내 주신 모든 분들께 감사드립니다. 그것은 C#의 개념을 잘 이해하는 데 도움이되었고 유용한 입력으로부터 많은 것을 배웠습니다. :)

===

원래 문제 :

지금 잠시 동안 검색 한 내 문제에 대한 해결책을 발견하지 않았습니다 : 나는 C#을 새로운 해요 및 작성하려고 MySql 연결을보다 쉽게 ​​만드는 클래스. 내 문제는 연결을 연 다음 닫는 것입니다. 그것은 여전히 ​​데이터베이스에서 열려 있으며 중단됩니다.

물론 'using'문을 사용하고 있지만 프로그램을 종료 한 후에도 연결이 여전히 열려 있으며 중단됩니다.

여기에 내 코드가 어떻게 생겼는지입니다 :

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 
    } 
} 
} 

클래스 데이터베이스 관리자가 연결을 열고 배치 할 때를 닫습니다 :

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); 
//} 

그래서, 내가 디버거 및 폐기에 체크 () -method가 호출되어 올바르게 실행됩니다. 내가 무엇이 누락 되었습니까? 내가 잘못했거나 오해 한 것이 있습니까?

도움을 주시면 감사하겠습니다.

인사말, 사이먼

PS : 그냥 경우, DataReader를() - 메서드 (업데이트 버전) :

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; 
       } 
      } 
     } 
    } 

좋아, 나는 항복 반환을 사용하려고 :

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

그리고 DataReader-method를 변경했습니다.

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; 
       } 
      } 
     } 
    } 

데이터를 검색 할 수있는 방식으로 작동하지만 여전히 동일한 문제가 있습니다. 연결이 제대로 닫히지 않았습니다. : (

+0

관리되지 않는 리소스가 없으므로 finalizer가 필요하지 않습니다. – SLaks

+0

사실입니다. 하지만 지금은 아프지 않습니다. 그렇지 않습니까? 내가 틀렸다면 나를 정정하십시오. 주요 목표는 더 이상 사용하지 않는 즉시 사용하지 않는 연결을 닫는 것입니다. 이 패턴은이 목표를 달성하는 쉬운 방법 인 것으로 보입니다. 나는 웹상의 많은 예에서 보여 지듯이 그것을 구현했다. 결국 중복 된 코드를 제거하기 위해 그것을 바꿀 것입니다. – Skalli

+1

성능에 영향을 미치지 만, 그렇지 않은 경우에는 없습니다. – SLaks

답변

15

임 확실!

편집 : Reader, Command 및 Connection 개체를 처리해야합니다.

편집 :이 꺼지면 ConnectionString에 파라미터 "풀링 = 거짓"또는 정적 메소드 MySqlConnection.ClearPool (연결) 및 MySQL의 문서에 따르면 MySqlConnection.ClearAllPools()

+0

현재 나는 이것들에 using-directive를 사용하고 있습니다. [link] (http://stackoverflow.com/questions/5567097/using-mysqlconnection-in-c-does-not-close-properly/5567722#5567722)를 참조하십시오. 아직도 아무 소용이 없습니다. – Skalli

+1

이 게시물에는 실제로 찾고있는 대답이 있지만 인식하지 못했습니다. 연결 풀링의 작동 방식에 익숙하지 않았기 때문입니다. 이제 이해하고 문제를 해결했습니다. 감사합니다. @Petoj. – Skalli

+0

아무런 문제가 없습니다. – Peter

5

using 문에도 Command와 DataReader를 래핑해야합니다.

+1

글쎄,하지만 어떻게? MySqlDataReader를 using 블록에 랩핑하면 로컬에서만 사용할 수 있습니다. DataReader 메서드는 개체를 using 블록에 반환합니다. 나는 이것이 using 블록의 끝에있는 MySqlDataReader-Object를 처리 할 것이라고 가정한다. using (MySqlDataReader result = db.DataReader (...) – Skalli

+0

MySqlDataReader를 반환하기 때문에 래핑 할 수 없다. MySqlDataReader가 끝날 때까지 MySqlCommand를 처리 할 필요가 없다고 생각합니다. 클로저로 돌아 오는 yield 반환을 조사해야합니다. –

+0

독자는 독자의 Disposed 이벤트를 처리 할 수 ​​있습니다. 'read.Disposed + = delegate {com.Dispose();}' – SLaks

-1

이 같은 것을 사용하여 살펴 유무 : mysqlconnection하지만 일부는 연결 풀링을 사용하고 대신 연결 풀에 넣 가까운 호출 할 때 닫히지 않는 SQL 서버 카운터에 대한

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

나는 그것을 들여다 볼 것입니다. 아주 흥미로 웠습니다. 이전에 수익률 수익률을 보지 못했군요. – Skalli

+0

@ user694856 http://stackoverflow.com/ 질문/850065/return-datareader-from-using-statement- –

+0

내 게시글을 보았습니다. [link] (http://stackoverflow.com/questions/5567097/using-mysqlconnection-in- c-do-not-close-properly/5567722 # 5567722) – Skalli

2

해결할는 MySQLConnection 폐쇄되지 범위를 벗어났습니다. 그러므로 당신은 그것을 사용할 때 사용해서는 안됩니다.

견적 ... "MySqlConnection이 범위를 벗어나면 닫히지 않으므로 MySqlConnection.Close 또는 MySqlConnection.Dispose를 호출하여 연결을 명시 적으로 닫아야합니다."

+2

using을 사용하면 객체가 범위를 벗어나면 close를 호출하고 처리해야합니다. try catch 블록을 사용하여 finally 블록에 닫고 처리하는 것과 같습니다. – Skalli

+1

@ 스 칼리가 맞습니다. using 문의 범위를 벗어나는 것은 언어 적 의미에서 범위를 잃는 것과 동일하지 않습니다. using 문은 Close를 호출합니다. –

관련 문제