在静态类中存储连接(ASP.NET)

时间:2010-03-04 23:43:15

标签: asp.net database class static

由于我使用的是Postgresql并且无法使用LINQ to SQL,因此我编写了自己的包装类。

这是学生班的一部分:

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属性移动到静态DB类。

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 个答案:

答案 0 :(得分:5)

最好不要将连接存储在静态字段中。按需创建连接对象,并让连接池管理您的连接。

答案 1 :(得分:3)

您可以为PostgreSQL启用connection pooling ,让pooler为您管理连接。然后你可以毫无顾虑地使用任何一段代码。即使您发出多个打开/关闭命令,pooler也会优化它们。

这为您提供了更多的灵活性,减少了对自定义管理解决方案的担忧,同时减少了代码和边缘情况。它取决于您正在使用的数据库提供程序。连接字符串中的某些内容如:

  

合并:正确还是错误。控制   是否使用连接池。   默认= True


如果您需要一个使用Postgres连接池的数据库提供程序,则选项 npgsqlNpgsql is a .Net data provider for Postgresql. 它支持连接池为described in the docs

答案 2 :(得分:1)

静态类是单例。这里的危险就是他们所提到的。因为他们总是活着,所以他们所引用的一切都不会被垃圾收集。

要查看是否是这种情况,请分析您的Web服务器内存。如果它总是增长而且从不收缩,那么你可能会不断地在一个永远不会被收集的静态类中添加引用。

尽管如此,我只是根据需要创建它,并完全避免所有这些。

修改

我的意思是不要担心在数据访问层中共享一个连接对象。如果您使用的提供程序支持连接池,则它将处理对数据库的实际连接。只需在数据访问层中的任何位置根据需要使用和处理连接对象。

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

我知道这样的代码相当大,笨重,重复,但这就是ADO.NET。只要您通过创建数据访问库/层在自己的类中隔离这些调用,它就非常易于管理。将ADO.NET对象隐藏在静态类中是危险的,因为您将不可避免地忘记在某处关闭连接或调用Dispose()。此外,您还有可能构建一个永远不会收集垃圾的大型对象图。

答案 3 :(得分:0)

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")*/; }
   }