Многопользовательский подключиться и сделать CRUD одновременно - PullRequest
1 голос
/ 09 мая 2011

Я использую ASP.NET Framework 4, IIS 7 и SQL Server 2008 R2.

У меня ошибка типа: {column} not found in selected DataSource, SQL Reader is close, ....

Это толькопроисходит, когда:

  1. Подключено несколько пользователей.
  2. Они делают вызовы CRUD (Создать, Извлечь, Обновить, Удалить) одновременно.

Как ни странно, этоизбежать моего улова:

try{
    Connexion_D.GetConnected();
    // doing CRUD
}
catch{
    // catching Error, avoid yellow page aspx
}
finally
{
    Connexion_D.CloseConnection();
} 

И мой класс соединения:

public class Connexion_D
{

    static public SqlConnection conn;
    static public SqlConnection GetConnected()
    {
        try
        {
            String strConnectionString = ConfigurationManager.ConnectionStrings["xxxxx"].ConnectionString;
            conn = new SqlConnection(strConnectionString);
        }
        catch (Exception excThrown)
        {
            conn = null;
            throw new Exception(excThrown.InnerException.Message, excThrown);
        }

        // Ouverture et restitution de la connexion en cours
        if (conn.State == ConnectionState.Closed) conn.Open();
        return conn;
    }
    static public Boolean IsConnected
    {
        get { return (conn != null) && (conn.State != ConnectionState.Closed) && (conn.State != ConnectionState.Broken); }
    }

    static public void CloseConnection()
    {
        // Libération de la connexion si elle existe
        if (IsConnected) conn.Close();
    }
}

Так что я не думаю, что код неправильный / есть ошибка.

Я думаюэто может быть конфигурация IIS и SQL-сервера.

Есть идеи?

Заранее спасибо.

1 Ответ

4 голосов
/ 09 мая 2011

Если я правильно понимаю, что вы делаете правильно, то это выглядит очень сомнительно:

static public SqlConnection conn;     
static public SqlConnection GetConnected() {         
    try         
    {             
        String strConnectionString = ConfigurationManager.ConnectionStrings["xxxxx"].ConnectionString;             
        conn = new SqlConnection(strConnectionString);
    } 
}

static public void CloseConnection() {           
    // Libération de la connexion si elle existe           
    if (IsConnected) conn.Close();       
}   

Вы работаете со статической переменной соединения, что означает, что когда вы закрываете ее, вы закрываете последнюю открытую переменную.

В многопользовательском сценарии это может произойти:

  • Пользователь A: Создать соединение (и вернуть соединение 1)
  • Пользователь A: выполнить запрос (запускается для соединения 1)
  • Пользователь B: создать соединение (и вернуть соединение 2)
  • Пользователь A: закрыть соединение (последнее открытое было 2, значит, закрыто)
  • Пользователь B: выполнить запрос (запускается для соединения 2, оно уже закрыто ... взрыв)

Кроме того, вам, вероятно, следует пересмотреть вопрос о том, чтобы ваше соединение являлось общедоступной переменной-членом:

static public SqlConnection conn;     

Обычно это считается плохой практикой и может привести к неожиданным / трудным отслеживанию ошибок в будущем, если какой-либо код вне вашего класса начнет возиться с его внутренними переменными.

EDIT:

Наиболее очевидным решением, по-видимому, было бы прекращение статического соединения. Ваш клиентский код может выглядеть примерно так:

try{
    // use using block around connection, calls dispose automatically when
    // block ends...
    using(var connectionWrapper = new Connexion_D()) {
        var connectedConnection = connectionWrapper.GetConnected();        
        // do CRUD
    }
}
catch{
    // catching Error, avoid yellow page aspx
    // Really you should probably be doing something with the exception (logging?)
    // particularly since you go to the effort of throwing it from your Connection_D
    // class.
}

с вашим кодом класса, похожим на:

/* Implement IDisposable to cleanup connection */
public class Connexion_D : IDisposable 
{
    public SqlConnection conn;

    public SqlConnection GetConnected()
    {
        try
        {
            String strConnectionString = ConfigurationManager.ConnectionStrings["xxxxx"].ConnectionString;
            conn = new SqlConnection(strConnectionString);
        }
        catch (Exception excThrown)
        {
            conn = null;
            throw new Exception(excThrown.InnerException.Message, excThrown);
        }

        // Ouverture et restitution de la connexion en cours
        if (conn.State == ConnectionState.Closed) conn.Open();
        return conn;
    }
    public Boolean IsConnected
    {
        get { return (conn != null) && (conn.State != ConnectionState.Closed) && (conn.State != ConnectionState.Broken); }
    }

    public void CloseConnection()
    {
        // Libération de la connexion si elle existe
        if (IsConnected) { 
            conn.Close();
            conn = null;
        }
    }

    // Implement IDisposable.
    // Do not make this method virtual.
    // A derived class should not be able to override this method.
    public void Dispose()
    {
        // Close connection
    }
}

См. this для получения дополнительной информации о реализации IDisposable.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...