如题。问题总结如下:
问题一: 不知道用哪个好?
问题二: 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;
}
问题一: 不知道用哪个好?
问题二: 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;
}
在建立一个连接后默认会创建相应的连接池。你确认你以后不会再用到与此相同的连接就可以用此语句而如果你还会用同样的连接操作时不应用此语句。影响性能
一般情况用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语句末尾或者中途引发了异常并且控制离开了语句块。
但是当对象使用using关键字的时候,必须实现IDisposable接口。using的使用和try-catch-finaly中,在finaly代码域调用Disposable方法效果一样。Using不能使用多个不同的类
using 展开编译之后就是 try-catch-finally 当然它只关注 finally,通过 finally 代码块来确保调用被 using 的对象 Dispose 方法 (被 using 的对象要求实现
IDispose 接口
{
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]可见是画蛇添足了。
使用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;
}
=======
推荐 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
是的,对于cls1和cls2类型相同就是这样写。也还可以写为(特别是cls1和cls2类型不同时可以写为):using(Class1 cls1=new Class1())
{
.......
using(Class2 cls2=new Class2())
{
.....
}
......
}所以只要Class2具有IDisposable接口,就无需在外边的Using内部写try...catch...finally,而写为Using更好。
问题是这个设计......我不会这样返回异常信息。如果一个方法遇到异常,方法本身就正常地向外抛出异常,而调用者就捕获异常,而不用这样定义ref rpstrErrorMessage 参数。
void PrintException(Exception ex)
{
while(ex!=null)
{
console.WriteLine(ex.ToString());
ex=ex.InnerException;
}
}如果你在调试或者自定义的打印输出时关注到InnerException,你不会得不到内嵌的信息。
是不是关掉连接后reader也就自动被关掉了?以前记得调用某个返回DataReader的共通方法时出错,如下
//returnReader = myCommand.ExecuteReader(); // 出错
returnReader = myCommand.ExecuteReader(CommandBehavior.CloseConnection); // 不出错了还有那个出错信息的捕捉应该怎么弄比较好? 帮忙提个建议,谢谢啊。
这两个没有可比性。你写的“方法二:使用Using”中的代码,返回的是list,而并不是返回reader,所以你写的代码不会有这个问题。
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执行有异常,如何在调用这个方法时捕捉异常,还是不大明白。小弟太菜了,不好意思。
其实跟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,而不是仅返回最上层的。
List<ClassA> listtry=null;
{
............
listtry =GetListg();
}
catch(Exception ex)
{
throw new MyException(string.Format("在用户{0}查询{1}经营报表调用GetListg()时系统异常。",user,report),ex);
}
.........
其实,如果你并不想这样对Exception再次使用自定义的方式包装一次,根本无需在调用GetListg时捕捉异常。