2014-04-09 5 views
3

중첩 된 SqlConnections이 가능할 지 모르겠지만 실제로는 그 것으로부터 멀리하고 싶습니다. 내 코드에서 범위 문제를 겪었고이를 해결하는 방법을 알아 내려고 노력 중입니다.중첩 된 SqlConnection을 피하려고 시도

최근까지 응용 프로그램을 시작할 때 열리는 글로벌 SqlConnection이 끝나면 닫혔습니다. 이제는 .NET의 연결 풀 개념을 발견 했으므로 코드를 변경하여 SqlCommand (또는 그 그룹)이 자체적으로 새로 생성되고 열리는 SqlConnection을 사용하고 .NET을 사용하여 풀과 함께 관리합니다 간접비.

지금 데 문제는 내가 같이 보일 코드의 여러 블록을 가지고있다

:

public static void WriteAction(MyActionClass action) 
{ 
    using (SqlConnection sqlConnection = new SqlConnection(ClassGlobal.ConnectionString)) 
    {  
     sqlConnection.Open(); 
     using (SqlCommand sqlCommand = new SqlCommand("Write the action to the DB", sqlConnection)) 
     { 
      sqlCommand.ExecuteNonQuery(); 
     } 
    } 
} 
다음 ClassGlobal.WriteAction() 함수는 다음과 같이 보입니다

using (SqlConnection sqlConnection = new SqlConnection(ClassGlobal.ConnectionString)) 
{  
    sqlConnection.Open(); 
    using (SqlCommand sqlCommand1 = new SqlCommand("SQL code here", sqlConnection)) 
    { 
     sqlCommand1.ExecuteNonQuery(); 
    } 
    using (SqlCommand sqlCommand2 = new SqlCommand("SQL code here", sqlConnection)) 
    { 
     sqlCommand2.ExecuteNonQuery(); 
    } 
    . 
    . 
    . 
    ClassGlobal.WriteAction(action); 
} 

하면서

보시다시피, SqlConnection의 범위 내에서 호출되는 안에 새로운 SqlConnection이 생성됩니다. 안좋다! 나는 이것을 피하려고 노력하고있다.

과거에는 이러한 using (SqlConnection) 블록이 없었고 모두 SqlCommands은 (글로벌) SqlConnection을 가리키고 있어도 문제가되지 않았습니다. 물론 단순히 아래로 using (SqlCommand)의 닫는 중괄호 아래 WriteAction()에 내 전화를 이동하지만 수 :

  1. 내가 그것을 전달하는 action 인스턴스는 종종 인스턴스화 SqlConnection 내가 좋겠의 범위 안에있는 동안 채워집니다 SqlConnection 범위 밖으로 이동하려면 더 많은 변경 (많은 작업)을해야합니다. 그것들이 많고 털이 많을 것이다.
  2. 실제로 WriteAction() 호출이 위의 예와 같이 SqlConnection 범위 안에있을 수 있으므로 TransactionScope에있는 내용을 모두 래핑 할 수 있으므로 더 좋을 것 같지만 확실히 좋은 아이디어 인 것 같습니다. .

여기 제가 계획하고있는 내용이 있습니다 만, 여러분 중 누구라도 이것이 우수 사례가 아니거나 더 나은 접근 방식을 제안 할 수 있는지 여부를 듣고 싶습니다. (나는 최근에 내 글로벌 SqlConnection이 좋은 습관이 아니며 그것을 고치는데 많은 시간을 소비한다는 것을 발견했다. 나는 미래에 이러한 발견을 피하고 싶다). 이 보이도록 나는 WriteAction() 함수에 매개 변수를 추가 대해

방법은 다음과 같이

public static void WriteAction(MyActionClass action, SqlConnection sqlConnection) 
{ 
    using (SqlCommand sqlCommand = new SqlCommand("Write the action to the DB", sqlConnection)) 
    { 
     sqlCommand.ExecuteNonQuery(); 
    } 
} 

이 오히려 SqlConnection 범위 WriteAction() 외부로 통화를 이동하는 것보다, 내가 단지를 추가 할 수 있음을 의미 SqlConnection을 함수의 매개 변수로 사용하여 함수 내에있는 SQLCommand이 해당 연결이 TransactionScope에 등록 된 경우에도 동일한 연결을 사용합니다.

public static void WriteAction(MyActionClass action) 
{ 
    using (TransactionScope transactionScope = new TransactionScope()) 
    { 
     using (SqlConnection sqlConnection = new SqlConnection(ClassGlobal.ConnectionString)) 
     { 
      sqlConnection.Open(); 
      WriteAction(action, sqlConnection); 
     } 
     transactionScope.Complete(); 
    } 
} 

이 좋은 생각처럼 보입니까 아니면 내가에 갈거야 :

내가 어떤 SqlConnection의 범위를 외부에서 WriteAction() 전화를 몇 인스턴스의

, 나는 다음과 같다 오버로드 기능을 쓸 수 있습니다 앞으로 2 년 후에이 결정을 내리시겠습니까?

+1

은 나에게 잘 보입니다. 그러나 트랜잭션을 단일 연산으로 처리하는 데 과부하가 발생합니다. 나는 그것이 단지 예시 일 뿐이라고 추측한다. – Jodrell

+0

물론 가능합니다. My WriteAction() 함수는 실제로 단일 SQL 작업 이상을 제공합니다. 감사. –

답변

2

SqlConnection 인스턴스를 메소드에 전달하는 것은 절대적으로 좋습니다. 그러나, 당신이 마지막 접근 방법인지 확실치 않다. SqlConnection없이 오버로드 된 메소드는 좋은 생각이다. 그것은 당신이 다른 새로운 오버로드를 더 잘 사용해야한다는 사실을 숨 깁니다. 그것은 지금 고쳐 져야하는 코드를 고치지 못하도록 코드를 컴파일합니다.

using 블록은 문제가 아니라 열린 연결입니다. 연결을 열지 않는 한 connection-pool은 물리적 연결을 열 필요가 없습니다. MSDN에서

using (SqlConnection sqlConnection = new SqlConnection(ClassGlobal.ConnectionString)) 
{  
    sqlConnection.Open(); 
    using (SqlCommand sqlCommand1 = new SqlCommand("SQL code here", sqlConnection)) 
    { 
     sqlCommand1.ExecuteNonQuery(); 
    } 
    using (SqlCommand sqlCommand2 = new SqlCommand("SQL code here", sqlConnection)) 
    { 
     sqlCommand2.ExecuteNonQuery(); 
    } 
    // ... 
    sqlConnection.Close(); 

    ClassGlobal.WriteAction(action); 

    // ... perhaps open it again here 
} 

:

사용자가 연결 Open를 호출 할 때마다

가, 풀러는 찾습니다

그래서 또한 당신이 WriteAction를 호출하기 전에 연결을 종료 할 수있는 실행 가능한 옵션입니다 풀에서 사용 가능한 연결. 풀링 된 연결을 사용할 수있는 경우 새 연결을 여는 대신 호출자에게 연결을 반환합니다. 응용 프로그램이 연결에서 Close을 호출하면 풀러는 풀링 대신 풀링 된 활성 연결 집합에 을 반환합니다. 연결이 풀로 반환되면 다음 Open 호출에서 다시 사용할 준비가되었습니다.

그래서 당신은 WriteAction의 중첩 using가 열려 외부 연결을 유지하지 않는 한 오랫동안 문제가되지 않습니다 것을 볼 수 있습니다. 연결 인스턴스와 실제 연결을 혼동하지 마십시오.

+0

감사. 그것은 확실히 좋은 충고입니다. 사실, SqlConnection.Close()의 목적을 이해하는 것은 이번이 처음입니다. 나는 닫는 중괄호가 똑같이하는 것을 보는 것에 대해 항상 궁금해했다. WriteAction() 호출 후 종종 SqlCommands가 더 많습니다. WriteAction()을 호출 한 후 연결을 전달하거나 sqlCommand.Open()을 다시 호출하는 것이 좋습니까? –

+1

@DewaldSwanepoel : 배경 정보가 없어도 맛의 문제입니다. 'ClassGlobal.WriteAction'는 모든 곳에서 호출 될 수있는 것처럼 들립니다. 그렇다면 호출자가'SqlConnection'을 기대하는 것은 좋지 않습니다. 다른 문항은 컨텍스트/클래스가없는 전역 메소드가 모범 사례인지 여부입니다. 그것은 OOP의 원칙에 위배됩니다. 또 다른 질문은, 각 단계에 대한 새로운 메소드를 작성하거나 모든 것에 대해 하나의 저장 프로 시저를 제공하여 적은 수의 작업을 수행하기 위해 외부 메소드를 리팩토링하지 않아야하는지 여부입니다. –