Является ли соединение с базой данных в этом классе «многоразовым»? - PullRequest
7 голосов
/ 21 сентября 2011

Я новичок в asp.net, так что это может быть очень простой вопрос, но я не могу понять.

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

Код и мой класс следующие:

namespace databaseFunctions
{
    public class databaseConnection
    {
private static string databaseConnectionString()
        {
            return "DRIVER={MySQL ODBC 5.1 Driver}; ........";
        }

        public static DataTable getFromDatabase(string SQL)
        {
            DataTable rt = new DataTable();
            DataSet ds = new DataSet();
            OdbcDataAdapter da = new OdbcDataAdapter();
            OdbcConnection con = new OdbcConnection(databaseConnectionString());
            OdbcCommand cmd = new OdbcCommand(SQL, con);
            da.SelectCommand = cmd;
            da.Fill(ds);
            try
            {
                rt = ds.Tables[0];
            }
            catch
            {   
                rt = null;
            }
            return rt;
        }

        public static Boolean insertIntoDatabase(string SQL)
        {

            OdbcDataAdapter da = new OdbcDataAdapter();
            OdbcConnection con = new OdbcConnection(databaseConnectionString());
            OdbcCommand cmd = new OdbcCommand(SQL, con);
            con.Open();
            try
            {
                cmd.ExecuteNonQuery();
                return true;
            }
            catch
            {
                return false;
            }

        }

}

Нет проблем при получении данных из базы данных,или вставьте данные в некоторую базу данных.Но.когда я пытаюсь получить last_insert_id () из базы данных mysql.я получаю только ноль.

Вот почему я думаю, что этот фрагмент кода, который я создал и скопировал из Интернета, создает новое соединение каждый раз, когда я вызываю «getFromDatabase (SQL)» *

Есть ли кто-нибудь, кто мог бы помочь мне с исправлением этого класса getFromDatabase (), чтобы поддерживать соединение с базой данных, пока я не скажу программе прекратить соединение?

Я полагаю, что это "новый OdbcConnection", который должен бытьизменилось?Можно ли проверить, есть ли уже живое соединение?Я делал это сотни раз в классической жерех, но теперь, с классами и прочим.Я полностью потерян.

Ответы [ 3 ]

10 голосов
/ 21 сентября 2011

Проблема, с которой вы сталкиваетесь, заключается в том, что вы закодировали себя в угол «новое соединение на действие». То, к чему вы действительно хотите стремиться, и считается наилучшей практикой, это «новое соединение на пакет действий».

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

namespace databaseFunctions
{
    public class databaseConnection:IDisposable
    {
        private OdbcConnection con;
        private string connectionString;

        public databaseConnection(string connectionString){
            this.connectionString = connectionString;
        }


        public void OpenConnection(){
            if (con == null || con.IsClosed ){ // we make sure we're only opening connection once.
                con = new OdbcConnection(this.connectionString);
            }
        }
        public void CloseConnection(){
            if (con != null && con.IsOpen){ // I'm making stuff up here
                con.Close();
            }
        }

        public DataTable getFromDatabase(string SQL)
        {
            OpenConnection();

            DataTable rt = new DataTable();
            DataSet ds = new DataSet();
            OdbcCommand cmd = new OdbcCommand(SQL, con);
            da.SelectCommand = cmd;
            da.Fill(ds);
            try
            {
                rt = ds.Tables[0];
            }
            catch
            {   
                rt = null;
            }
            return rt;
        }

        public Boolean insertIntoDatabase(string SQL)
        {
            OpenConnection();

            OdbcCommand cmd = new OdbcCommand(SQL, con);
            con.Open();
            try
            {
                cmd.ExecuteNonQuery();
                return true;
            }
            catch
            {
                return false;
            }

        }


        // Implementing IDisposable method
        public void Dispose(){
            CloseConenction();
        }
    }
}

Теперь в следующий раз, когда вы используете свой класс, сделайте что-то вроде

using (DatabaseConnection db = new DatabaseConnection()){
    db.InsertIntoDatabase(...);
    db.GetLastInsertID();
    db.GetFromDatabase(...);
}

В конце этого блока кода, так как он является IDisposeable, он закроет это соединение для вас в методе dispose.


Вещи, которые я изменил:

  • реализовано IDisposable интерфейс
  • изменил методы со статических на методы класса.
  • добавлены новые методы открытия закрывающего соединения
  • перемещена переменная соединения в область уровня класса
  • добавил аргумент в конструктор, который позволяет вам передать строку подключения (вы должны поместить эту строку подключения в ваш Web.Config

редактирует:

  • конструктор принимает в соединении строку за предложение.

4 голосов
/ 21 сентября 2011

Да, код, который вы разместили, создает новое соединение с базой данных каждый раз, когда вызывается метод, но это не проблема.Проблема в том, что он не удаляет соединение должным образом.Способ обработки чего-то подобного заключается в следующем:

using (OdbcConnection con = new OdbcConnection("yourconnectionsstring"))
{
   con.open();
   OdbcCommand command = new OdbcCommand("command_text",con);
   command.ExecuteQuery(); //or what ever you need to do
}

Таким образом, соединение устанавливается правильно, так как использование является просто синтаксическим сахаром для try/finally

Что вам нужно сделать, этовыполнить 2 оператора SQL в той же транзакции так, чтобы вы вставили запись в первый оператор SQL и извлекли последний вставленный идентификатор на следующей вставке перед завершением транзакции.Например:

 using (OdbcConnection con = new OdbcConnection("yourconnectionsstring"))
    {
       con.open();
       OdbcTransaction tran = con.BeginTransaction()
       OdbcCommand command = new OdbcCommand("first_sql_statement_here",con);
       command.ExecuteNonQuery(); 
       command.CommandText = "select last_insert_id();";
       int result =command.ExecuteScalar(); 
       tran.commit();
    }

Это в значительной степени идея.

1 голос
/ 21 сентября 2011

Вы должны позволить пулу соединений обрабатывать ваши соединения;Это означает, что вы Close() устанавливаете каждое соединение как можно скорее и создаете новое только в самый последний момент.

Так что да, продолжайте создавать новые для отдельных транзакций.

...