Почему я получаю эту ошибку подключения к базе данных в SQL Server? - PullRequest
0 голосов
/ 04 апреля 2009

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

public class dbOpnClse
{
    SqlConnection con = new SqlConnection();
    public SqlConnection openConnection()
    {
        con.ConnectionString ="server=SERVERNAME;database=Test;uid=###;pwd=#####";
        con.Open();
        return con;
    }
    public void closeConnection()
    {
        con.Close();
    }
}

Проблема в том, что я получаю исключение «Не разрешено изменять свойство« ConnectionString ». Текущее состояние соединения открыто». Есть ли ошибка в этом коде подключения? Пожалуйста помоги! Я использую C # .net 2005 и SQL Server 2000

Ответы [ 5 ]

8 голосов
/ 04 апреля 2009

Я думаю, что во второй раз, когда вы вызываете openConnection, вы еще не закрыли его, и поэтому вы пытаетесь установить свойство connectionstring уже открытого соединения. Это не разрешено.

Вместо этого в .Net вы хотите, чтобы ваши методы стиля openConnection() фактически создавали новое соединение каждый раз, когда они вызываются, в соответствии с шаблоном фабрики, чтобы соединение могло быть правильно удалено. Нечто подобное:

private SqlConnection CreateConnection()
{
    //even better if the connection string is pulled from a config file
    var result = new SqlConnection("Your connection string here");
    result.Open();
    return result;
}

Не будет соответствующего метода закрытия. Вместо этого мы будем полагаться на шаблон IDisposable, чтобы убедиться, что соединение всегда закрыто правильно. Затем вы будете использовать эту функцию и соединение в таком методе, как этот:

public DataTable GetRecords(int SomeValue)
{
    var result = new DataTable();

    string sql = "SELECT * FROM [MyTable] WHERE [SomeIntColumn]= @SomeValue";

    using (var cn = CreateConnection() )
    using (var cmd = new SqlCommand(sql, cn) )   
    {
        cmd.Parameters.Add("@SomeValue", SqlDbType.Int).Value =  SomeValue;

        using (var rdr = cmd.ExecuteReader() )
        {
           result.Load(rdr);
        }
    }
    return result;  
}

Операторы using работают с любым объектом, который реализует интерфейс IDisposable, и они гарантируют, что ваше соединение закрыто, даже если выдается исключение.

Также обратите внимание, что я сделал метод CreateConnection () закрытым. Это потому, что этот класс станет вашим уровнем доступа к данным. Сделав соединение частным, вы обеспечите хороший уровень базы данных, где единственный способ общения с базой данных - пройти через этот класс. Любой код, который должен общаться с БД, должен быть здесь. Если этот класс начинает становиться слишком большим, вы можете пометить этот метод как internal, а не как private, и переместить слой доступа к данным в его собственную сборку (отдельный проект в Visual Studio). Теперь ключ состоит в том, чтобы ограничить ваши методы принятием строго типизированных входных данных для параметров. Не пытайтесь создать универсальный метод, который позволяет вам напрямую передавать в sql. Так лежит безумие.

Наконец, НИКОГДА НИКОГДА НЕ НИКОГДА подключитесь к базе данных из вашего приложения через учетную запись sa, и размещение сведений о вашей учетной записи sa на общедоступном веб-сайте не так уж и ярко.

1 голос
/ 04 апреля 2009

Бину,

В вашем коде множество проблем. Во-первых, вы не должны вставлять строку подключения в код - вы должны извлечь ее из файла конфигурации, чтобы вы могли изменить ее при развертывании. Во-вторых, не входите в свою базу данных с учетной записью sa !! Только не делайте этого - поверьте мне в этом.

В-третьих, я настоятельно рекомендую вам использовать интерфейс IDisposable и блок Using, чтобы гарантировать, что ваше соединение всегда закрыто. На самом деле, вы зависите от кода потребления для вызова closeConnection.

Попробуйте этот пример кода:

public class MyConnClass : IDisposable
{
    public static string ConnectionString { get; set; }
    protected SqlConnection conn;

    public MyConnClass()
    {
        conn = new SqlConnection(ConnectionString);
        conn.Open();
    }

    public void Dispose()
    {
        conn.Close();
    }
 }

В вашем коде инициализации (например, Global.asax.cs в веб-приложении) установите строку статического соединения следующим образом:

    MyConnClass.ConnectionString = ConnectionString;

В ваших потребляющих классах вы будете использовать что-то вроде:

using (MyConnClass myConn = new MyConnClass())
{

    // Database code

}

Обновление : Еще одна вещь, которую я бы посоветовал вам рассмотреть, - это изменить приведенный выше код, чтобы он стал основой для уровня доступа к данным (DAL), а не только для соединения. То есть, поместите туда объект команды SQL и создайте код, чтобы упростить вашу общую стратегию доступа к данным. То есть просто помещать Connection в отдельный класс немного бесполезно, поскольку, как указывает Джоэл, объекты SqlConnection сами по себе одноразовые. Преимущество полноценного DAL заключается в том, что он может радикально упростить доступ к данным. Например, мой DAL позволяет мне писать такие вещи, как:

using (MyQueryClass myQuery = new MyQueryClass())
{
   myQuery.Command("Update...").ParamVal("@P1", 1).ParamVal("@P2", 2).Execute();
   return myQuery.Command("Select ...").ParamVal("@Param", SomeVal).ReturnList<SomeType>();
}

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

0 голосов
/ 04 апреля 2009

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

Вам следует прочитать эту статью о лучших практиках ADO.NET

0 голосов
/ 04 апреля 2009
    namespace databaseOp 
{ 
public class dbOpnClse 
{ 
SqlConnection con; 

public SqlConnection openConnection() 
{ 
    //Try this...
    con = new SqlConnection("server=CHEMPAKASSERIL;database=Test;uid=sa;pwd=jeevan");

    //Not this...
    //con.ConnectionString ="server=CHEMPAKASSERIL;database=Test;uid=sa;pwd=jeevan"; 
    con.Open(); 
    return con; 
} 

public void closeConnection() 
{ 
    con.Close(); 
}

    }

}
0 голосов
/ 04 апреля 2009

Предположительно, вы пытаетесь сделать это (т.е. изменить свойство 'ConnectionString') в другом месте вашего кода.

Рекомендуется открывать соединения и закрывать их снова, как только блок кода завершает использование соединения (используйте оператор using), и разрешить пул соединений заботиться о соединениях.

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