鉴于此代码:
using (var conn = new SqlConnection("..."))
{
conn.Open();
using (var cmd = conn.CreateCommand())
{
cmd.CommandText = "...";
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
// ...
}
}
}
}
我习惯为我的数据访问编写try / catch / finally块,但是,我正在接触“使用”这似乎是一种更简单的方法。但是,我正在试图找出如何捕获可能发生的异常。
你能举个例子说明你如何捕捉异常吗?
已编辑添加:
我被引导相信“使用”是我的try / catch / finally块的替代品。我知道使用不会捕获异常。那怎么替代呢?
答案 0 :(得分:57)
using
并非旨在捕获异常;它旨在为您提供一种简单的方法,将try
/ finally
包裹在需要处理的对象周围。如果您需要捕获和处理异常,那么您需要将其扩展为完整的try
/ catch
/ finally
或将其包含try
/ {{1}围绕整个事情。
要回答您的修改(catch
替换using
/ try
/ catch
?),请注意,不是。大多数情况下,当使用一次性资源时,您不会在那里处理异常,因为通常没有什么用处可以做。因此,它提供了一种方便的方法来确保资源被清理,无论您尝试做什么工作与否。
通常,处理可支配资源的代码工作的级别太低,无法确定正确操作失败的原因,因此会将异常传播给调用者,调用者可以决定要采取的操作(例如,重试,失败,日志等)。
你倾向于使用带有可支配资源的finally
块的唯一地方是你要翻译异常(我假设你的数据访问层在做什么)。
答案 1 :(得分:12)
using (var cmd = new SqlCommand("SELECT * FROM Customers"))
{
cmd.CommandTimeout = 60000;
...
}
是
的语法糖var cmd = new SqlCommand("SELECT * FROM Customers");
try
{
cmd.CommandTimeout = 60000;
...
}
finally
{
if (cmd != null)
cmd.Dispose();
}
所以当人们告诉你“使用”是try / catch /的替代品时,他们暗示你应该使用长手形式但是加入你的catch块:
var cmd = new SqlCommand("SELECT * FROM Customers");
try
{
cmd.CommandTimeout = 60000;
...
}
catch (Exception ex)
{
...//your stuff here
}
finally
{
if (cmd != null)
cmd.Dispose();
}
答案 2 :(得分:11)
将所有using语句包装到try / catch中。像其他人一样,使用的是清理实现IDisposable接口的类
try
{
using (var conn = new SqlConnection("..."))
{
conn.Open();
using (var cmd = conn.CreateCommand())
{
cmd.CommandText = "...";
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
// ...
}
}
}
}
}
catch(Exception ex)
{
//Handle, log, rethrow exception
}
答案 3 :(得分:7)
如果你想捕获异常,你可能应该回到使用try / catch / finally。只需将.Dispose()调用放在finally块中。
答案 4 :(得分:6)
使用语句与异常无关。使用块只是确保在使用块中的对象上调用Dispose,当它退出该块时。即:
using(SqlConnection conn = new SqlConnection(conStr))
{
//use conn
}//Dispose is called here on conn.
如果打开连接会引发异常(或该块中的任何其他内容),它仍然会冒泡到顶部,就像任何其他无法处理的异常一样。
答案 5 :(得分:3)
您仍然可以像以前一样完全捕获(或忽略)异常。关键是你不再需要担心处理数据库连接。
即,如果您的应用程序要求您因某些其他原因(例如,日志记录)捕获异常,请继续,但如果您只想处置数据库连接,则不再需要这样做:
using (SqlConnection conn = new SqlConnection(...))
{
// do your db work here
// whatever happens the connection will be safely disposed
}
如果由于其他原因想要捕获异常,您仍然可以这样做:
try
{
using (SqlConnection conn = new SqlConnection(...))
{
// do your db work here
// whatever happens the connection will be safely disposed
}
}
catch (Exception ex)
{
// do your stuff here (eg, logging)
// nb: the connection will already have been disposed at this point
}
finally
{
// if you need it
}
答案 6 :(得分:0)
将try catch
块放入一个using
块中。他们专用于对象处置的隐式finally
语句将在外部块catch
语句及其内容之前执行。