Хранение соединения в статическом классе (ASP.NET) - PullRequest
2 голосов
/ 05 марта 2010

Поскольку я использую Postgresql и не могу использовать LINQ to SQL, я написал свои собственные классы-оболочки.

Это часть класса Student:

public class Student : User
{
    private static NpgsqlConnection connection = null;

    private const string TABLE_NAME = "students";

    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Password { get; set; }

    /// <summary>
    /// Reads data from the data reader and moves it to the Student class.
    /// </summary>
    private static void ReadFields(Student student, NpgsqlDataReader dr)
    {
        student.Id = Int32.Parse(dr["id"].ToString());
        student.FirstName = dr["first_name"].ToString();
        student.LastName = dr["last_name"].ToString();
        student.Password = dr["password"].ToString();
    }

    /// <summary>
    /// Updates the student
    /// </summary>
    public void Update()
    {
        Connect();
        Run(String.Format("UPDATE " + TABLE_NAME + " SET first_name='{0}', last_name='{1}', password='{2}' WHERE id={3}", FirstName, LastName, Password, Id));
        connection.Dispose();
    }

    /// <summary>
    /// Inserts a new student
    /// </summary>
    public void Insert()
    {
        Connect();
        Run(String.Format("INSERT INTO " + TABLE_NAME + " (first_name, last_name, password) VALUES ('{0}', '{1}', '{2}')",FirstName, LastName, Password));
        connection.Dispose();
    }

    private static void Run(string queryString)
    {
        NpgsqlCommand cmd = new NpgsqlCommand(queryString, connection);
        cmd.ExecuteScalar();
        cmd.Dispose();
    }

    private static void Connect()
    {
        connection = new NpgsqlConnection(String.Format("Server=localhost;Database=db;Uid=uid;Password=pass;pooling=false"));
        connection.Open();
    }

    //....

Итак, как вы видите, при каждом запросе INSERT, DELETE, UPDATE я использую метод Connect (), который подключается к базе данных.Я не осознавал, насколько это было глупо, прежде чем мне пришлось ждать 10 минут, чтобы вставить 500 строк, поскольку было 500 подключений к базе данных.

Поэтому я решил переместить свойство Connection в статический класс БД.

public static class DB
{
    private static NpgsqlConnection connection = null;
    public static NpgsqlConnection Connection
    {
        get
        {
            if (connection == null)
            {
                connection = new NpgsqlConnection(String.Format("Server=localhost;Database=db;Uid=uid;Password=pass;pooling=false"));
                connection.Open();
            }
            return connection;
        }
    }

    public static void Run(string queryString)
    {
        NpgsqlCommand cmd = new NpgsqlCommand(queryString, connection);
        cmd.ExecuteScalar();
        cmd.Dispose();
    }
}

Теперь работает!Я заменяю все Run методы в классе Student на DB.Run

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

Ответы [ 4 ]

5 голосов
/ 05 марта 2010

Лучше не хранить соединение в статическом поле. Создайте объект подключения по требованию и позвольте пулам подключений управлять вашими подключениями.

3 голосов
/ 05 марта 2010

Вы можете включить пул соединений для PostgreSQL и позволить пулеру управлять соединениями за вас. Тогда вы можете без проблем использовать любой фрагмент кода. Даже когда вы запускаете несколько команд открытия / закрытия, диспетчер их оптимизирует.

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

Объединение: верно или неверно. управления используется ли пул соединений. По умолчанию = True


Если вам нужен поставщик базы данных, который использует пул соединений для Postgres, один из вариантов: npgsql : Npgsql is a .Net data provider for Postgresql. Он поддерживает пул соединений, как указано в документации .

.
1 голос
/ 05 марта 2010

Статические классы являются синглетонами. Опасность здесь в том, на что они ссылаются. Поскольку они всегда остаются в живых, все, на что они ссылаются, не будет собирать мусор.

Чтобы узнать, так ли это, профилируйте память вашего веб-сервера. Если он всегда растет и никогда не сжимается, вы можете постоянно добавлять ссылки в статический класс, который никогда не будет собран.

Честно говоря, я бы создал его только по мере необходимости и полностью избежал всего этого.

EDIT:

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

using (var connection = new NpgsqlConnection("your connection string"))
{
    //your data access stuff.
}

Я знаю, что такой код довольно большой, громоздкий и повторяющийся, но это ADO.NET. Пока вы изолируете эти вызовы в их собственных классах путем создания библиотеки / слоя доступа к данным, это очень управляемо. Скрывать объекты ADO.NET в статическом классе опасно, потому что вы неизбежно забудете закрыть соединение или вызвать Dispose(). Кроме того, вы рискуете построить большой граф объектов, который никогда не будет собирать мусор.

0 голосов
/ 04 ноября 2011
public class Dataconnect
{

   public static string connstring = ConfigurationSettings.AppSettings["SQLConnection"].ToString();
   SqlConnection objcon = new SqlConnection(connstring);
   SqlCommand objcmd = new SqlCommand();

   public bool Opencon()
   {
       try {
           if (objcon.State == ConnectionState.Closed)
           {
               objcon.Open();
           }
           objcmd.Connection = objcon;
           return true;           
       }
       catch (Exception ex) { throw new Exception("Error: In Open connesction"); return false; }
   }

   public bool Closecon()
   {
       try
       {
           if (objcon.State == ConnectionState.Open)
           {
               objcon.Close();
           }
           objcmd.Dispose();
           return true;
       }
       catch (Exception ex) { throw new Exception("Error: In Close connesction"); return false; }
   }

   public static int ExecuteQuery(SqlCommand sqlcmd)
   {           
       try
       {
           Dataconnect objdc = new Dataconnect();
           int affectedrecord = 0;
           if (objdc.Opencon() == true)
           {
               sqlcmd.Connection = objdc.objcon;
               affectedrecord = sqlcmd.ExecuteNonQuery();
               objdc.Closecon();
               objdc = null;
               return affectedrecord;
           }
           else { return affectedrecord; }

       }
       catch (Exception ex) { throw ex;/* new Exception("Error: In ExecuteNonquery");*/ }

   }

   public static DataTable Generatedatatable(SqlCommand sqlcmd) 
   {
       try { Dataconnect objdc = new Dataconnect();

       if (objdc.Opencon() == true)
       {
           sqlcmd.Connection = objdc.objcon;
           SqlDataReader dr;
           DataTable objdt = new DataTable();
           dr = sqlcmd.ExecuteReader();
           objdt.Load(dr);
           objdc.Closecon();
           objdc = null;
           return objdt;
       }
       else { return null; }
       }
       catch (Exception Exception) { throw Exception /*new Exception("Error: In Generatedatatable")*/; }
   }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...