下面的这段程序,在.Net 1.1 中没有问题,但是到了2.0 中就有问题了,每次运行程序的时候都会报告需要调试,并指出  Myconn.Close(); 这一句有错误,意思大概是说.NET Framework Data Provider 出错。请问各位。我的这样写法有错误么?应该怎么样改进?=======================================
using System;
using System.Collections.Generic;
using System.Text;
using System.Data.OleDb;namespace TestLib
{
    class dbcontrols
    {
        OleDbConnection Myconn = new OleDbConnection("Provider=SQLOLEDB;Data Source=127.0.0.1;Persist Security Info=True;User ID=sa;Initial Catalog=pubs;pwd=sa");
        OleDbCommand mycomm;        public dbcontrols()
        {
            Myconn.Open();
        }
        ~dbcontrols()
        {
            Myconn.Close();
            Myconn.Dispose();
        }
        public bool Run(string runstr)
        {            bool result = true;
            try
            {
                mycomm = new OleDbCommand(runstr, Myconn);
                mycomm.ExecuteNonQuery();
            }
            catch
            {
                result = false;
            }            return result;
        }
    }
}

解决方案 »

  1.   

    ~dbcontrols()
            {
                Myconn.Close();
                Myconn.Dispose();
            }改成        ~dbcontrols()
            {
              if(this.Myconn.State!=ConnectionState.Closed){
                Myconn.Close();
                Myconn.Dispose();
                }
            }
      

  2.   

    你说的这种方法也试过了.确信conn已经被 open 了。并且if(this.Myconn.State!=ConnectionState.Closed)是成功的,会执行到 Myconn.close() 这句的时候还是一样的问题
      

  3.   

    其实你可以用using(){... }避免手动关闭OleDbConnection 。
    不过照理说你这么写应该没错阿,试试看
      

  4.   

    如果把open 和 close 都写在 method 里面,就没有任何错误,只要写在构造和析构里面,在2.0中就会出这样的问题,
      

  5.   

    找到问题所在了,在你的类的析构函数调用前,系统垃圾回收器会自动先清除对象(这里是你的Myconn),也就是说,在你的想调用Myconn.Close(); 这一句时,实际上此对象已不存在了。
    测试代码:
    ===================
    public class Class1 : IDisposable
    {
        SqlConnection Myconn = new SqlConnection("Data Source=.;Initial Catalog=Morning2;Integrated Security=True");
        SqlCommand mycomm;    string bug;
        public Class1()
        {
            Myconn.Open();
        }
        ~Class1()
        {
            try
            {
                Myconn.Close();
                Myconn.Dispose();
            }
            catch (Exception ee)
            {
                bug = ee.ToString();
                
            }
        }    public string  Run()
        {
            string flag="";
            string runstr = "SELECT [DepartmentId], [DepartName] FROM [morning_Department]";
            try
            {
                mycomm = new SqlCommand(runstr, Myconn);
                flag = mycomm.ExecuteScalar().ToString();
            }
            catch
            {        }        return flag;
        }
        #region IDisposable 成员    public void Dispose()
        {
            //Myconn.Close();
            //Myconn.Dispose();
        }    #endregion
    }
    ========================
    调用代码:
            try
            {
                using (Class1 c = new Class1())//强制回收
                {
                    string i = c.Run();
                    Response.Write("flag=" + i);
                }
            }
            catch (Exception ee)
            {            Response.Write(ee.ToString());
            }
    =======================建议改进方法:实现IDisposable接口,不要用析构函数。(参见代码中Dispose()函数里注销掉的2句,你可以删除析构函数,把相关代码放到这里。外部用using(){...}方式调用)
    你可以在上述代码的析构函数和Dispose函数下断点,看看。
      

  6.   

    看到了你的用法,但是我现在有个特殊的情况,现在的工程写了很大一部分了,
    三层, 上面的代码是在 数据操作层上,方法比较少。但在逻辑层对数据层的调用上方法写的太多了,这样用 using 的方法,要改的地方太多了。有没有别的办法呢
      

  7.   

    另外你在前面说的"找到问题所在了,在你的类的析构函数调用前,系统垃圾回收器会自动先清除对象(这里是你的Myconn),也就是说,在你的想调用Myconn.Close(); 这一句时,实际上此对象已不存在了。"但是在我调试的时候 ,出错时候 Connection.State 是 Open 状态,并没有被回收吧
      

  8.   

    chenzhixin(我是农民的儿子) ( ) 信誉:100  2006-03-25 13:05:00  得分: 0  
     
     
       ~dbcontrols()
            {
                Myconn.Close();
                Myconn.Dispose();
            }改成        ~dbcontrols()
            {
              if(this.Myconn.State!=ConnectionState.Closed){
                Myconn.Close();
                Myconn.Dispose();
                }
            }
      
     
    本人认为正解
      

  9.   

    吃饱了写什么析构啊...这是.NET~~~~GC会析构的,在dispose里close就行了,还搞2次干嘛....
    实在需要析构的时候
    protected override void Finalize()
    {
    try{关你的连接,释放你的非托管}
    finally{base.Finalize();}
    }
      

  10.   

    C#基础的东东没搞清楚。
    .net中的析构函数与C++中意义是不一样的。因为GC的垃圾收集是不可预测的。
    而且
    Myconn.Close();
    Myconn.Dispose();
    是重复使用。没必要如此一般地如果是托管资源,不必要自已进行释放,但在析构中可以使用
    obj =null;
    非托管资源实现IDisposable接口,手动释放。
    Close是Dispose的包装。而且没理解ADO.net 与ADO的用法区别的意义
    ADO.net没必要保持一个连接,SQL Server 支持连接池
    ADO.net中一定要尽快地释放连接。
    一般可以使用using来确保实现了IDisposable的对象的资源释放
      

  11.   

    已经改用了 Using 的方法.感谢以上