2011-12-21 3 views
2

소개신속하게 데이터베이스

내가 웹 응용 프로그램을 (쓰고 있어요/삭제 만들 때 오류 메시지 "연결이 비활성화되었습니다"C의 #/ASP.NET MVC 3, .NET 프레임 워크 4, MS SQL 서버 2008, System.Data.ODBC 데이터베이스 연결) 및 데이터베이스 생성/삭제에 관한 꽤 문제가 있습니다.

응용 프로그램에서 데이터베이스를 만들고 삭제할 수 있어야한다는 요구 사항이 있습니다.

문제

애플리케이션은 함수 스트레스 테스트를 실패한다. 더 구체적으로 말하자면, 클라이언트가 신속하게 같은 이름의 데이터베이스를 다시 생성, 삭제, 생성하면 (5 번째 요청시 ~) 서버 코드가 ODBCException '연결이 비활성화되었습니다.'. 이 동작은 테스트가 수행 된 모든 시스템에서 발생합니다. 정확히 실패한 요청은 5 번째가 아닌 그 값의 어딘가에있을 수 있습니다. 예외에 인터넷 검색

연구

은 매우 낮은 출력했다 -를 제외하고는 매우 일반적인 하나 찾을 수 없습니다 아날로그 문제를 보인다. 제가 발견 한 제안 중 하나는 제 개발 Windows 7이 서버 OS가 아닌 수많은 동시 연결을 처리하지 못할 수도 있다는 것입니다. Windows 2008 Server에 응용 프로그램을 설치하려고 시도했습니다. 동작이 거의 변경되지 않았습니다. 예외가 발생하기 전에 요청이 처리되었습니다.

데이터베이스는 다음과 같이 저장 프로 시저를 사용하여 만든

코드 및 구현에 대한 추가 의견 :

CREATE PROCEDURE [dbo].[sp_DBCreate] 
...  
    @databasename nvarchar(124)  -- 124 is max length of database file names 
AS 
    DECLARE @sql nvarchar(150); 
BEGIN 
... 
    -- Create a new database 
    SET @sql = N'CREATE DATABASE ' + quotename(@databasename, '['); 
    EXEC(@sql); 

    IF @@ERROR <> 0 
     RETURN -2; 
...  
    RETURN 0; 
END 

데이터베이스는 다음과 같은 SP 사용하여 삭제합니다 : 두 SP에서

CREATE PROCEDURE [dbo].[sp_DomainDelete] 
... 
    @databasename nvarchar(124)  -- 124 is max length of database file names 
AS 
    DECLARE @sql nvarchar(200); 
BEGIN 
... 
    -- check if database exists 
    IF EXISTS(SELECT * FROM [sys].[databases] WHERE [name] = @databasename) 
    BEGIN 
     -- drop all active connections 
     SET @sql = N'ALTER DATABASE' + quotename(@databasename, '[') + ' SET SINGLE_USER WITH ROLLBACK IMMEDIATE'; 
     EXEC(@sql); 
      -- Delete database 
     SET @sql = N'DROP DATABASE ' + quotename(@databasename, '['); 
     EXEC(@sql); 

     IF @@ERROR <> 0 
      RETURN -1; --error deleting database 
    END 
    --ELSE database does not exist. consider it deleted. 

    RETURN 0; 
END 

을 나는 온 전성 검사와 같이 관련성이 적은 부분을 생략했습니다.

나는 모든 ORM을 사용하지 않고 모든 SP는 OdbcCommand 인스턴스를 사용하여 코드에서 호출됩니다. 새 OdbcConnection이 각 함수 호출에 대해 작성됩니다.

나는 누군가가 내게이 문제에 대한 단서를 줄 수 있기를 진심으로 바랍니다.

UPD : 데이터베이스를 신속하게 만들면 똑같은 문제가 발생합니다. 데이터베이스 삭제 코드에 대한 제안을 주신 모든 분들께 감사드립니다. 그러나 좀 더 일반적인 문제에 대한 해결책이나 최소한 힌트를 원합니다. DB 삭제 없이도 발생합니다.

UPD2은 : SP에 사용되는 다음 코드는 호출

public static int ExecuteNonQuery(string sql, params object[] parameters) 
{ 
    try 
    { 
     var command = new OdbcCommand(); 
     Prepare(command, new OdbcConnection(GetConnectionString() /*irrelevant*/), null, CommandType.Text, sql, 
      parameters == null ? 
      new List<OdbcParameter>().ToArray() : 
      parameters.Select(p => p is OdbcParameter ? (OdbcParameter)p : new OdbcParameter(string.Empty, p)).ToArray()); 

     return command.ExecuteNonQuery(); 
    } 
    catch (OdbcException ex) 
    { 
     // Logging here 
     throw; 
    } 
} 

public static void Prepare(
    OdbcCommand command, 
    OdbcConnection connection, 
    OdbcTransaction transaction, 
    CommandType commandType, 
    string commandText, 
    params OdbcParameter[] commandParameters) 
{ 
    if (connection.State != ConnectionState.Open) 
    { 
     connection.Open(); 
    } 
    command.Connection = connection; 
    command.CommandText = commandText; 
    if (transaction != null) 
    { 
     command.Transaction = transaction; 
    } 
    command.CommandType = commandType; 
    if (commandParameters != null) 
    { 
     command.Parameters.AddRange(
      commandParameters.Select(p => p.Value==null && 
       p.Direction == ParameterDirection.Input ? 
        new OdbcParameter(p.ParameterName, DBNull.Value) : p).ToArray()); 
    } 
} 

샘플 연결 문자열 :

Driver={SQL Server}; Server=LOCALHOST;Uid=sa;Pwd=<password here>; 
+0

'SET SINGLE_USER :

이 코드를 사용해보십시오. –

+0

@MartinSmith : 그게 실제로 우리가 원하는 것입니다. 우리는 데이터베이스의 빠른 삭제를 불가능하게하는 장기 실행 요청을 가지고 있습니다. 내가 당신의 요지를 보았지만 -이 진술은 수영장에 매달려있는 연결을 방해 할 수 있습니다. 그리고 그것이 그러한 행동의 원인이 될 수 있습니다 ... 어쨌든, 우리는 데이터베이스를 삭제하지 않더라도 동일한 문제를 겪고 있습니다. 5 개 이상의 데이터베이스 (물론 다른 이름)를 추가해도 동일한 결과가 발생합니다. –

+0

나는이 오류 메시지를 호출 프로그램에서 받았다고 생각합니까? 연결 풀링이 비활성화되었는지 확인 했습니까? – ChrisBD

답변

1

좋아요. OdbcConnection에 대한 범위 문제가있을 수 있지만 작업을 마친 후에는 연결을 닫지 않는 것처럼 보입니다.이는 풀 관리자가 사용되지 않는 연결을 닫고 시간 제한에 따라 풀로 되돌려 놓을 수 있음을 의미 할 수 있습니다. using 블록은 완료되면 자동으로 연결을 닫고 처리하여 연결 풀로 반환되도록합니다. 이 데이터베이스를 사용하여 다른 연결을 죽일 것이다 ROLLBACK IMMEDIATE` 함께

public static int ExecuteNonQuery(string sql, params object[] parameters) 
{ 
    int result = 0; 
     try 
     { 
      var command = new OdbcCommand(); 
      using (OdbcConnection connection = new OdbcConnection(GetConnectionString() /*irrelevant*/)) 
      { 
       connection.Open(); 
       Prepare(command, connection, null, CommandType.Text, sql, 
         parameters == null ? 
              new List<OdbcParameter>().ToArray() : 
              parameters.Select(p => p is OdbcParameter ? (OdbcParameter)p : new OdbcParameter(string.Empty, p)).ToArray()); 

       result = command.ExecuteNonQuery(); 
      } 

     } 
     catch (OdbcException ex) 
     { 
      // Logging here 
      throw; 
     } 
    return result; 
} 
+0

답변 해 주셔서 감사합니다! 그게 문제를 해결할 수 있다면 가장 어리석은 버그 일 것입니다. 내일 당신의 제안을 점검 할 것입니다. –

+0

고마워, 크리스, 네 제안이 맞았 어. 약간의 수정으로 나는 이것을 안정적으로 만들었다. P. 완전히 나의 이전 코멘트 아래 구독. 이것은 내가 만든 가장 어리석은 버그입니다. –

+0

도움이 된다니 기쁘다. – ChrisBD

관련 문제