如题。问题总结如下:
问题一: 不知道用哪个好?
问题二: using里面可以加上Try...Catch吗?
问题三: 在Finally里要不要加上连接的Dispose()方法呢?
 
两个方法的代码我都写了,如下:    方法一: 使用TryCatchFinally:                    //方法一: 使用TryCatchFinally
    public static List<ClassA> GetListTryCatch()
    {
                List<ClassA> list = new List<ClassA>();
                string queryString = @"select * from tableA";         
        OracleConnection connection = null;
        
        try
        {
        connection = new OracleConnection(connectionString);
        OracleCommand command = new OracleCommand();
        command.Connection = connection;
        command.CommandText = queryString;
        connection.Open();
        OracleDataReader reader = cmd.ExecuteReader();
        while (reader.Read())
        {
                    ClassA ca = new ClassA();
                    ca.ItemName = reader.GetString(0);
                    ca.TargetValue = reader.GetDouble(1);
                    list.Add(ca);
        }
}
catch (Exception)
{
throw;
}
    finally
    {
connection.Close();
// connection.Dispose();  // 不知道要不要加这句
    }

        return list;
    }
方法二: 使用Using:     //方法二: 使用Using
    public static List<ClassA> GetListUsing()
            {
                List<ClassA> list = new List<ClassA>();
                string queryString = @"select * from tableA";                // use using
                using (OracleConnection connection = new OracleConnection(connectionString))
                {
                    OracleCommand command = new OracleCommand(queryString, connection);
                    connection.Open();
                    using (OracleDataReader reader = command.ExecuteReader())
                    {
                        // Always call Read before accessing data.
                        while (reader.Read())
                        {
                            ClassA ca = new ClassA();
                            ca.ItemName = reader.GetString(0);
                            ca.TargetValue = reader.GetDouble(1);
                            list.Add(ca);
                        }
                    }
                }                return list;
            }

解决方案 »

  1.   

    觉得try catch就可以了3 用dispose 好
      

  2.   

    // connection.Dispose();  // 不知道要不要加这句
    在建立一个连接后默认会创建相应的连接池。你确认你以后不会再用到与此相同的连接就可以用此语句而如果你还会用同样的连接操作时不应用此语句。影响性能
    一般情况用using,但有的情况不得不手动开关
      

  3.   

    using里面也是需要try的,只是他代替了finally的左右而以
      

  4.   

    using语句,定义一个范围,在范围结束时处理对象。
    场景:
    当在某个代码段中使用了类的实例,而希望无论因为什么原因,只要离开了这个代码段就自动调用这个类实例的Dispose。
    要达到这样的目的,用try...catch来捕捉异常也是可以的,但用using也很方便。
    例如:using (Class1 cls1 = new Class1(), cls2 = new Class1())
    {
      // the code using cls1, cls2
    } // call the Dispose on cls1 and cls2
    这里触发cls1和cls2的Dispose条件是到达using语句末尾或者中途引发了异常并且控制离开了语句块。
      

  5.   

    两者完全没有可比性...using只是自动调用具有IDisposable接口对象的Dispose方法,不能也不可能代替try...
      

  6.   

    using 清理非托管资源,不受GC控制的资源。Using结束后会隐式的调用Disposable方法。
    但是当对象使用using关键字的时候,必须实现IDisposable接口。using的使用和try-catch-finaly中,在finaly代码域调用Disposable方法效果一样。Using不能使用多个不同的类
      

  7.   

    其实.net本身并没有using,c#、vb.net编译器将using编译为合适的try...catch...finally,所以你不用画蛇添足地再自己在Using内外部再重复写try...catch...finally。如果你使用reflector这类反编译工具,它会按照c#的方式解析为using,所以你应该使用MSIL来看真正的底层代码,就可以看到Using本身实际就是try...catch....finally。
      

  8.   

    如 sp123所说, 
    using 展开编译之后就是 try-catch-finally 当然它只关注 finally,通过 finally 代码块来确保调用被 using 的对象 Dispose 方法 (被 using 的对象要求实现 
    IDispose 接口
      

  9.   

    例如代码static void Main()
    {
        using (var x = new Domain.Client())
        {
            int i = 0;
        }
    }被编译为[code=MSIL].method private hidebysig static void Main() cil managed
    {
        .entrypoint
        .maxstack 2
        .locals init (
            [0] class [Domain]Domain.Client client,
            [1] int32 num,
            [2] bool flag)
        L_0000: nop 
        L_0001: newobj instance void [Domain]Domain.Client::.ctor()
        L_0006: stloc.0 
        L_0007: nop 
        L_0008: ldc.i4.0 
        L_0009: stloc.1 
        L_000a: nop 
        L_000b: leave.s L_001d
        L_000d: ldloc.0 
        L_000e: ldnull 
        L_000f: ceq 
        L_0011: stloc.2 
        L_0012: ldloc.2 
        L_0013: brtrue.s L_001c
        L_0015: ldloc.0 
        L_0016: callvirt instance void [mscorlib]System.IDisposable::Dispose()
        L_001b: nop 
        L_001c: endfinally 
        L_001d: nop 
        L_001e: ret 
        .try L_0007 to L_000d finally handler L_000d to L_001d
    }
    [/code]而在Using里边添加try...catch...finally的代码static void Main()
    {
        using (var x = new Domain.Client())
        {
            try
            {
                int i = 0;
            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
                ((IDisposable)x).Dispose();
            }
        }
    }被编译为[code=MSIL].method private hidebysig static void Main() cil managed
    {
        .entrypoint
        .maxstack 2
        .locals init (
            [0] class [Domain]Domain.Client client,
            [1] int32 num,
            [2] bool flag)
        L_0000: nop 
        L_0001: newobj instance void [Domain]Domain.Client::.ctor()
        L_0006: stloc.0 
        L_0007: nop 
        L_0008: nop 
        L_0009: ldc.i4.0 
        L_000a: stloc.1 
        L_000b: nop 
        L_000c: leave.s L_0012
        L_000e: pop 
        L_000f: nop 
        L_0010: rethrow 
        L_0012: nop 
        L_0013: leave.s L_001f
        L_0015: nop 
        L_0016: ldloc.0 
        L_0017: callvirt instance void [mscorlib]System.IDisposable::Dispose()
        L_001c: nop 
        L_001d: nop 
        L_001e: endfinally 
        L_001f: nop 
        L_0020: nop 
        L_0021: leave.s L_0033
        L_0023: ldloc.0 
        L_0024: ldnull 
        L_0025: ceq 
        L_0027: stloc.2 
        L_0028: ldloc.2 
        L_0029: brtrue.s L_0032
        L_002b: ldloc.0 
        L_002c: callvirt instance void [mscorlib]System.IDisposable::Dispose()
        L_0031: nop 
        L_0032: endfinally 
        L_0033: nop 
        L_0034: ret 
        .try L_0008 to L_000e catch [mscorlib]System.Exception handler L_000e to L_0012
        .try L_0008 to L_0015 finally handler L_0015 to L_001f
        .try L_0007 to L_0023 finally handler L_0023 to L_0033
    }
    [/code]可见是画蛇添足了。
      

  10.   

    想了想还是用TryCatch好了,虽然代码得多写点,但是万一SQL文有错误(如表不存在等),至少可以捕捉到异常并显示出来。
    使用TryCatch的话还得关掉OracleDataReader吧? 在最后的Finally里关掉可以吧? 
    貌似OracleDataReader.ExecuteReader方法还可以传一个参数(CommandBehavior的属性),这里不用可以吧?最后实现的代码如下,如果有错的话请帮忙指点出来,感激不尽!            public static List<ClassA> GetList(ref rpstrErrorMessage)
                {
                    List<ClassA> list = new List<ClassA>();
                    string queryString = @"select * from tableA";                
                    OracleConnection connection = null;
                    
                    try
                    {
                        connection = new OracleConnection(connectionString);
                        OracleCommand command = new OracleCommand();
                        command.Connection = connection;
                        command.CommandText = queryString;
                        connection.Open();
                        OracleDataReader reader = cmd.ExecuteReader();
                        while (reader.Read())
                        {
                            ClassA ca = new ClassA();
                            ca.ItemName = reader.GetString(0);
                            ca.TargetValue = reader.GetDouble(1);
                            list.Add(ca);
                        }                    
                    }
                    catch (Exception ex)
                    {
                        rpstrErrorMessage = ex.Message;
                    }
                    finally
                    {
    reader.Close();
                        connection.Close();
                    }                
                    
                    return list;
                }
      

  11.   

    问题一: 不知道用哪个好?
    =======
    推荐 using ! 你可能知道能被using 的对应要求实现 IDispose 为什么呢?
    以为
    using(SqlConnection conn = ..) {}
    编译展开之后是
    try {
    SqlConnection conn = ...
    }
    finally {
    conn.Dispose();   // 总是假定你有 Dispose 可以被使用
    }问题二: using里面可以加上Try...Catch吗?
    =====
    当然问题三: 在Finally里要不要加上连接的Dispose()方法呢? 
    ===
      finally
                    {
                        connection.Close();
                        // connection.Dispose();  // 不知道要不要加这句 // 不用 Dispose 内部调用 Close() 
                    }           4. 因此楼主需要认真的理解 using 到底是如何工作的?
    从上面分析,试问如果 Connection  没有实现 IDispose 接口没有提供 Dispose 那么 Connection 功能是完整的吗? 档案是肯定的!5. using 与 IDispose 实际上是一种“设计模式”,两者结合便于“高效编程”(恼人的try-cath-finally)同时也保证“释放资源”(假定类的实现者总是在Dispose正确释放资源)6. SqlConnection.Close() 这个方法是 “功能”方法,没有它就是不完整的!Hope helpful
      

  12.   

    尽管在没有异常时对运行速度没有什么大影响(只是多了两个跳转),但是代码不够整洁。使用Using是一种让编程更轻松和效果可靠的做法,因为你就无需再去费心关心finally中的代码的写法问题,出了问题也无需费心思去查找finally中的代码有没有误写错误。
      

  13.   

    尽管在没有异常时对运行速度没有什么大影响(只是多了两个跳转)   -->   在Using再写try...catch...finally尽管在没有异常时对运行速度没有什么大影响(只是多了两个跳转)
      

  14.   


    是的,对于cls1和cls2类型相同就是这样写。也还可以写为(特别是cls1和cls2类型不同时可以写为):using(Class1 cls1=new Class1())
    {
        .......
        using(Class2 cls2=new Class2())
        {
           .....
        }
        ......
    }所以只要Class2具有IDisposable接口,就无需在外边的Using内部写try...catch...finally,而写为Using更好。
      

  15.   

    那如果写using语句而不用TryCatch的话,我如何做到如果执行SQL文出错时能捕捉到出错信息?还望指教。
      

  16.   

    哦,我注意到楼主的“方法二:使用Using”中的代码。实际上,我此时会只写一个Using,而内部的Using不会去写。写Using的目的应该是很明确地去调用IDisposable.Dispose,只要及时关闭数据库连接(释放到连接池)这个目的达到就够了,没有必要在里边调用另一个Using。
      

  17.   


    问题是这个设计......我不会这样返回异常信息。如果一个方法遇到异常,方法本身就正常地向外抛出异常,而调用者就捕获异常,而不用这样定义ref rpstrErrorMessage 参数。
      

  18.   

    问下我只用USING ,不用TRY CATCH 能捕获异常吗?
      

  19.   

    这应该说你对Exception没有仔细分析其结构。Exception有一个递归的InnerException结构,如果你试试你就能打印所有层次的异常信息,例如:
    void PrintException(Exception ex)
    {
        while(ex!=null)
        {
           console.WriteLine(ex.ToString());
           ex=ex.InnerException;
        }
    }如果你在调试或者自定义的打印输出时关注到InnerException,你不会得不到内嵌的信息。
      

  20.   

    可是如果reader那里不用using的话,关掉连接,而没有关掉reader,不会有问题吧? 
    是不是关掉连接后reader也就自动被关掉了?以前记得调用某个返回DataReader的共通方法时出错,如下
    //returnReader = myCommand.ExecuteReader();  // 出错
    returnReader = myCommand.ExecuteReader(CommandBehavior.CloseConnection);  // 不出错了还有那个出错信息的捕捉应该怎么弄比较好? 帮忙提个建议,谢谢啊。
      

  21.   


    这两个没有可比性。你写的“方法二:使用Using”中的代码,返回的是list,而并不是返回reader,所以你写的代码不会有这个问题。
      

  22.   

    只用一个using的话,改成这样对吗?
                public static List<ClassA> GetListg()
                {
                    List<ClassA> list = new List<ClassA>();
                    string queryString = @"select * from tableA";                // use using
                    using (OracleConnection connection = new OracleConnection(connectionString))
                    {
                        OracleCommand command = new OracleCommand(queryString, connection);
                        connection.Open();
                        OracleDataReader reader = command.ExecuteReader(CommandBehavior.CloseConnection);
                        while (reader.Read())
                        {
                            ClassA ca = new ClassA();
                            ca.ItemName = reader.GetString(0);
                            ca.TargetValue = reader.GetDouble(1);
                            list.Add(ca);
                        }
                        reader.Close();
                    }                return list;
                }
    如果SQL执行有异常,如何在调用这个方法时捕捉异常,还是不大明白。小弟太菜了,不好意思。
      

  23.   


    其实跟Using没有半点关系。事实上,一般来说,调用者应该捕获然后继续抛出异常:
    ............
    try
    {
        ............
        List<ClassA> list=GetListg();
    }
    catch(Exception ex)
    {
        threw new MyException(string.Format("在用户{0}查询{1}经营报表调用GetListg()时系统异常。",user,report),ex);
    }
    .........然后由界面层统一机制来处理异常。就算模仿你15楼的逻辑在底层来处理异常,我们也可以写:............
    string errmessage=string.Empty;
    try
    {
        ............
        List<ClassA> list=GetListg();
    }
    catch(Exception ex)
    {
        while(ex!=null)
        {
           errmessage += ex.Message;
           ex = ex.InnerException;
        }
    }
    .........
    实际上,就算你在15楼中的代码,也应该在rpstrErrorMessage中返回ex中递归的各层Exception的Message,而不是仅返回最上层的。
      

  24.   

    ............
    List<ClassA> listtry=null;
    {
        ............
        listtry =GetListg();
    }
    catch(Exception ex)
    {
        throw new MyException(string.Format("在用户{0}查询{1}经营报表调用GetListg()时系统异常。",user,report),ex);
    }
    .........
    其实,如果你并不想这样对Exception再次使用自定义的方式包装一次,根本无需在调用GetListg时捕捉异常。
      

  25.   

    还有谢谢大家,也特别感谢Jinglecat。终于明白了富农是怎么炼成的,呵呵  (热心+实力^_^)