解决方案 »

  1.   

    多线程是很常见的。例如编写那种asp.net程序的人,程序部署到生产服务器以后,asp.net系统处理每一个消息请求都是在线程中的,同一时间可能有并发处理几十个请求。那么那种搞什么“共享DbConnection”的代码,就只能是你自己单机玩玩儿而已,在多并发下肯定要出现“已有打开的与此命令相关联的 DataReader,必须首先将它关闭”这类BUG了。后边的BUG我懒的看了。因为第一个问题已经说明,你没有采取正确的ADO.NET并发访问下进行编程的方法。进行ADO.NET编程,类似于            List<MyObj> result;
                  using (var conn = new OracleConnection(cnStr))
                  {
                      conn.Open();
                      var comm = conn.CreateCommand();
                      comm.CommandText = "select e.TheName, e.Number from Users as e where ..........";
                      comm.CommandType = System.Data.CommandType.Text;
                      result = ( from DbDataRecord record in comm.ExecuteReader()                             select new MyObj{ 
                                                  Name = (string)record["TheName"],
                                                  Value = (double)record["Number"]
                                             };
                               ).ToList();
                  }   
    这样来返回 List<T> 对象集合,保证及时关闭 conn,同时也绝不向外界抛出 DataReader。
      

  2.   

    跳出你这个问题,来强调一下编程之道:你编写多线程程序来测试出你的底层代码有BUG,这样才能发现自己的基础代码(例如SQLHelper)里的一大堆设计错误。应该庆幸发现得足够早。
      

  3.   

    你的所谓 Conn.rs 这是个“老鼠屎”,这是一个严重的设计BUG。在你的代码中应该new一个新的连接对象,例如                    if (Hang1.Length != 0)//Dgv第一行,有人在线
                        {
                            try
                            {
                              using(var conn = CreateNewConnection())
                              {
                                conn.Open();
                                Int32 result = 0;
                                string sql = string.Format("Update Abiao Set Code='" + ZU1_h1 + "' Where ID=1");
                                SqlCommand cmd = new SqlCommand(sql, conn);
                                result = cmd.ExecuteNonQuery();
                                if (result < 1)
                                {
                                    new SqlCommand("Update Bbiao Set Code='' Where BLie='" + ZU1_h1 + "'", conn).ExecuteNonQuery();
                                }
                                else
                                {
                                    new SqlCommand("Insert Into Cbiao (Code)values('" + ZU1_h1 + "')", conn).ExecuteNonQuery();
                                }
                              }
                            }
                            catch (Exception ex)
                            {
                                //...
                            }
                        }需要在局部中临时创建数据库连接,然后访问完,尽快释放(在using结束会自动释放)。其它地方也是一样。不是搞什么“共享DbConnection”,那种以为“只要创建一次数据库逻辑连接然后就能到处访问”的做法就会造成你这一堆BUG。
      

  4.   

    别说是多线程访问,就算是单线程访问,例如你的某个读取数据库循环语句中调用了另外一个功能,这个功能也需要读取数据,那么就会出现“已有打开的与此命令相关联的 DataReader,必须首先将它关闭”的错误。而你的代码不但有这类设计错误,并且在调用 Conn.rs.Open()和 Conn.rs.Close() 上存在着胡乱穿插随机调用的问题。这说明你没有推敲、用头脑“模拟演练”过程程序调用的复杂过程。回到第一个编程知识,(至少在使用SQL Server的ADO.Net引擎驱动时)刚入门的asp.net程序员也懂得“使用DbConnection必须单独创建、使用完即时关闭”的。除非你漠视这种警告,而简单地抄写早些年某些人写的垃圾博客上的代码,否则应该不会写出那样的代码。
      

  5.   

    我的Conn.cs文件中有New,不知道,是否可以。
    class Conn
        {
            private static string cn = "Data Source=127.0.0.1;Initial Catalog=Db2013;User ID=sa;pwd=123456;MultipleActiveResultSets=True";
            public static SqlConnection rs = new SqlConnection(cn);
        }请各位指导。谢谢。
      

  6.   

    还有你还是没理解楼上的意思,每次访问数据库创建一次连接语句:
    你最多就是传递一个非静态的sql连接字符串变量吧,范例:            OracleConnection conn = null;
                DataTable dataTable = null;
                try
                {
                    conn = new OracleConnection(conStr);
                    conn.Open();
                    OracleCommand cmd = new OracleCommand();
                    cmd.CommandText = sqlText;
                    cmd.Connection = conn;
                    if (parms != null && parms.Count > 0)
                    {
                        cmd.Parameters.AddRange(parms.ToArray());
                    }
                    OracleDataAdapter oda = new OracleDataAdapter(cmd);
                    DataSet dataSet = new DataSet();
                    oda.Fill(dataSet);
                    dataTable = dataSet.Tables[0];
                }
                catch (Exception ex)
                {
                    log.Error(sqlText);
                    log.Error(ex.Message);
                    throw ex;
                }
                finally
                {
                    conn.Close();
                }
      

  7.   

    请问,我在窗体加载的时候,怎么样写。让数据显示到dataGridView中
    然后,每N秒计时器里刷新又怎么样写。谢谢