写WebService,在WebService类中写一个将数据库连接对象作为它的成员变量在构造函数中创建且打开连接,以便让所有的方法都调用同一个连接对象,这样在事务处理时就可以控制了。
比如方法A开启事务,调用方法B,方法A提交事务。但是现在有个问题,因为每次调用WS都执行一次构造函数,而.Net的延迟调用析构函数,而我是在析构中将连接关闭的,导致连接数超过连接池限制报错,同时同存占用也猛增。我又不想调用GC强制垃圾回收,这样做可能将连接直接释放了,不知道能不能放回到连接池中。

解决方案 »

  1.   

    调GC好像也很影响。Net程序的性能,记得书上是这样讲的。我这种做法好像适合一个线程的情况,现在这种多线程的程序做数据库连接应该如何做呢?我真的迷糊了。还有,哪位有好点的O-R map,介绍一下,我学习一下他们是如何弄的。谢谢了。
      

  2.   

    using System;
    using System.Collections;
    using System.ComponentModel;
    using System.Data;
    using System.Diagnostics;
    using System.Web;
    using System.Web.Services;namespace demo1
    {
    /// <summary>
    /// Service1 的摘要说明。
    /// </summary>
    public class Service1 : System.Web.Services.WebService
    {
    public Service1()
    {
    //CODEGEN: 该调用是 ASP.NET Web 服务设计器所必需的
    InitializeComponent();
    //方法一使用 Service1_Disposed 事件
    this.Disposed+=new EventHandler(Service1_Disposed);
    }
    private IContainer components = null;
    private void InitializeComponent()
    {
    }
    protected override void Dispose( bool disposing )
    {
    if(disposing)
    {
    //方法二在这里 <释放的代码>
    int i=0;
    }
    if(disposing && components != null)
    {
    components.Dispose();
    }
    base.Dispose(disposing);
    }
    [WebMethod]
    public string HelloWorld()
    {
    throw new ApplicationException("abc");
    return "Hello World";
    } private void Service1_Disposed(object sender, EventArgs e)
    {
    System.Diagnostics.Debug.WriteLine("Service1_Disposed");
    }
    }
    }
      

  3.   

    Dispose 不管是否有异常都回走
    除非你的 服务器 挂了.....
      

  4.   

    最后把 连接对象 Dispose 了就可以不用 close 
    Dispose 隐含 close 的
      

  5.   

    to 比如方法A开启事务,调用方法B,方法A提交事务。你如何写
      

  6.   

    连接对象作为类成员变量.在方法A中开启事务,调用方法B,方法A提交事务.在方法A和方法B使用类成员的数据库连接对象.public class test {
       private OleDbConnection dbConn=null;
       public test {
         dbConn=new....;
       }
       public void A() {
         System.Data.OleDb.OleDbTransaction myTran=null;
         myTran=dbConn.BeginTransaction();
         //一些数据操作
         B();
         myTran.Commit();
       }
       public void B() {
         //使用dbConn作一些数据操作
       }
    }
      

  7.   

    按照上面写的,应该没有什么问题。
    不过找我的做法,可能如下更好:public void A() {
    System.Data.OleDb.OleDbTransaction myTran=null;
    myTran=dbConn.BeginTransaction();
    //一些数据操作
    B( myTran );
    }public void B( OleDbTransaction myTran ) {
    //使用dbConn作一些数据操作
    }
      

  8.   

    你的ws是用一个connection,还是多个connection。
      

  9.   

    WS是用一个Connection.因为用的是同一个Connection,所以我不能在方法B里关掉连接.因为我不确定是否有其它方法在使用这个连接,以至于关闭连接的任务我只能放在析构函数里,但是.Net执行析构函数也太慢了,以至于用光了连接池,并且内存的占用率也疯涨.而且有时候,方法B是一个独立的功能,是不需要其它方法来调用的,这里保留一个参数显然不太好.当然最好的方法是在每个方法中都新建连接(因为有连接池所以不会影响效率),但是这样的话又需要我传递事务对象到各个方法.关键是我想知道大家如何处理这样的问题.举个例子:方法A写入库单,方法B写库存.
    有时候的逻辑是在方法A中调方法B.
    而有时候不需要写入库就直接写库存的情况,那么就直接调方法B.
    这种情况下难道非要给方法B一个Transaction 参数吗?
      

  10.   

    to 因为用的是同一个Connection,所以我不能在方法B里关掉连接.因为我不确定是否有其它方法在使用这个连接,以至于关闭连接的任务我只能放在析构函数里,但是.Net执行析构函数也太慢了,以至于用光了连接池,并且内存的占用率也疯涨.我以前的做法是整个ws用一个静态的connection,那么所有的web方法都是用此connection去操作数据库。那么在webservice初始化的时候去初始化connection,最后在application结束的时候去关闭。
    其他的时候不去关闭connection。
      

  11.   

    using System;
    using System.Data;
    using System.Data.OleDb;
    namespace demo1
    {
    /// <summary>
    /// test 的摘要说明。
    /// </summary>
    public class test:IDisposable
    {
    private OleDbConnection dbConn=null;
    /// <summary>
    /// 判断对象是否被调用过 Dispose
    /// </summary>
    private bool disposed = false; public test()
    {
    dbConn = new OleDbConnection("连接串");
    } ~test()
    {
    Dispose(false);
    } /// <summary>
    /// 静态调用函数 如 test.Exec();
    /// </summary>
    public static void Exec()
    {
    using(test t = new test())
    {
    t.A();
    }

    } public void TryRollback(IDbTransaction tran)
    {
    try
    {
    tran.Rollback();
    }
    catch(Exception ex)
    {
    System.Diagnostics.Trace.WriteLine("TryRollback Error:" + ex.ToString());
    }
    } public void A() 
    {
    System.Data.OleDb.OleDbTransaction myTran=null;
    myTran=dbConn.BeginTransaction();
    try
    {
    B();
    myTran.Commit();
    }
    catch(OleDbException ex)
    {
    System.Diagnostics.Trace.WriteLine("test.A catch 01:"+ex.ToString());
    TryRollback(myTran);
    } } public void B() 
    {
    //使用dbConn作一些数据操作
    } #region IDisposable 成员 public void Dispose()
    {
    Dispose(true);

    GC.SuppressFinalize(this); }
    private void Dispose(bool disposing)
    {

    if(!this.disposed)
    {

    if(disposing)
    {
    if(dbConn!=null)
    {
    dbConn.Dispose();
    }

    }
    else
    {
    System.Diagnostics.Trace.WriteLine("没有 Dispose 本对象");
    }
    }
    disposed = true;         
    }
    #endregion
    }
    }
      

  12.   

    To:我以前的做法是整个ws用一个静态的connection,那么所有的web方法都是用此connection去操作数据库。那么在webservice初始化的时候去初始化connection,最后在application结束的时候去关闭。
    其他的时候不去关闭connection。
    --------------------------------------------------------------------------------
    只使用一个连接不是会影响数据库的并发吗?如果有100个客户端同时发起请求那速度~~汗.如果一个操作用一秒,那第100个用户就得要等上近2分钟.感觉不太好.不过也是一种方法,我以前是这样写的.
    在Application_start里新建一个连接,在End里关闭连接.感觉影响并发所以才改掉的.如果让你现在写,你还是按前的方法写吗?
      

  13.   

    FlashElf(銘龘鶽) 大哥:   我还是不确定你的方法,Dispose方法你的是要在析构函数里去调用吧?可是析构函数是由CLR来调用的,而我现在的问题就是在用光了连接的时候CLR还没有执行析构函数.   我现在的做法就是在析构里关闭连接.   现在暂时使用GC.Collect()来释放内存.发现效果还好,内存变化无异常.只是知道这种方式不太好