【问题标题】:Is it safe to use static methods for accessing database in following scenario在以下情况下使用静态方法访问数据库是否安全
【发布时间】:2013-03-05 04:56:36
【问题描述】:

我正在将一个 asp 网站升级到 asp.net。我正在尝试遵循多 teir 方法。 我的基本 dal 层如下,它返回一个数据表并插入一个给定的查询。

using System;
using System.Configuration;
using System.Data;
using MySql.Data.MySqlClient;

public class mydatautility
{
    public mydatautility()
    {
    }
    public static DataTable Table(string query)
    {
        string constr = ConfigurationManager.ConnectionStrings["db_con"].ConnectionString;
        DataTable table = new DataTable();
        try
        {
            using (MySqlConnection con = new MySqlConnection(constr))
            {
                con.Close();
                MySqlCommand com = new MySqlCommand(query, con);
                MySqlDataAdapter da = new MySqlDataAdapter(com);
                con.Open();
                da.Fill(table);
                con.Close();
                da = null;
                com = null;
                con.Dispose();
            }
        }
        catch (Exception)
        {
        }
        return table;
    }
    public static int Insert_intoemployee(string query)
    {
        string constr = ConfigurationManager.ConnectionStrings["db_con"].ConnectionString;
        int done = 0;
        try
        {
            using (MySqlConnection con = new MySqlConnection(constr))
            {
                MySqlCommand com = new MySqlCommand(query, con);
                con.Open();
                done = com.ExecuteNonQuery();
                con.Close();
                com = null;
                con.Dispose();
            }
        }
        catch (Exception)
        {
        }
        return done;
    }
}

我不确定运行 2 个并发查询时会发生什么。
如何测试它是否存在并发问题?

【问题讨论】:

  • 您可能正在寻找“SQL Profiler”。
  • 安全。每个查询都是独立的。
  • 我觉得我应该指出ExecuteNonQuery 返回受影响的行数。所以你的 Insert 方法实际上并没有返回主键..如果那是你想要的。你正在寻找ExecuteScalar
  • 不,没关系。受影响的行数。我不需要主键。

标签: c# asp.net mysql


【解决方案1】:

不会有并发问题,因为每个请求都有自己的线程,并且静态方法对每个线程都有单独的调用堆栈。不过,代码中有一些建议。

using System;
using System.Configuration;
using System.Data;
using MySql.Data.MySqlClient;

public static class mydatautility//change to Utilities
{
    public mydatautility()//not required in this scenario
    {
    }
    public static DataTable Table(string query) //change method name to GetTable
    {
        string constr = ConfigurationManager.ConnectionStrings["db_con"].ConnectionString;
        DataTable table = new DataTable();
        try
        {
            using (MySqlConnection con = new MySqlConnection(constr))
            {
                con.Close();//not required
                using(MySqlCommand com = new MySqlCommand(query, con))
                {
                MySqlDataAdapter da = new MySqlDataAdapter(com);
                con.Open();
                da.Fill(table);
                con.Close();
                da = null;// reduntant, not required
                com = null;// reduntant, not required
                con.Dispose();// reduntant, not required
                }
            }
        }
        catch (Exception)
        {
        }
        return table;
    }
    public static bool InsertEmployee(string query)// consider changing int to bool since you only require result of operation
    {
        string constr = ConfigurationManager.ConnectionStrings["db_con"].ConnectionString;
        int done = 0;
        try
        {
            using (MySqlConnection con = new MySqlConnection(constr))
            {
                Using(MySqlCommand com = new MySqlCommand(query, con))
                {
                con.Open();
                done = com.ExecuteNonQuery();
                con.Close();
                com = null;// reduntant, not required
                con.Dispose();// reduntant, not required
                }
            }
        }
        catch (Exception)
        {
        }
        return done > 0; // checks rows affected greater than 0
    }
}

【讨论】:

  • +0。你有很好的代码建议(在using 块结束之前也错过了con.Close()),但是你解释为什么没有并发问题是有问题的。每个请求都在自己的线程上运行这一事实只会增加出现问题的机会,而绝不会消除它们。
  • 我在这种情况下也提到过,静态方法每个线程都有单独的调用堆栈,因此不会出现并发问题。我读到每个请求都在单独的线程上执行,stackoverflow.com/questions/1416351/…stackoverflow.com/questions/8084143/…
  • 但是为什么在页面类中声明变量时会出现并发问题。我已经看到该变量对于所有页面实例都具有相同的变量,为此我必须转移到会话。如果我错了,请纠正我。
  • 在页面中,您将静态变量与部分类相关联。因此,每个请求都有相同的副本。在这种情况下,通过在 Utilities 类中声明一个静态变量,所有线程都将是单一副本。如果您更改它,所有引用都会更新。这些静态变量按 AppDomain 存储。
  • 在这些方法中,您传递的变量是非静态的,一旦函数结束就会过期(从调用堆栈中删除)。因此,每个函数调用都有自己的调用堆栈。希望这会有所帮助。
【解决方案2】:

在这种情况下使用静态方法是安全的。静态方法中的变量与并发调用是隔离的!也可以看到这个链接:variable in static methods inside static class

【讨论】:

    【解决方案3】:

    我认为这是安全的,但不好的做法。如果您使用静态方法访问实时资源,那么您希望如何对它们进行单元测试?你不能再真正模拟数据库访问了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多