在WCF方法返回DataSet时,using语句的资源释放方式是否恰当?
在WCF中返回DataSet时的资源释放方式对比分析
问题描述
在WCF方法中返回DataSet时,第一种使用using语句处理SqlConnection、SqlCommand、SqlDataAdapter的资源释放方式是否合适?还是必须采用第二种实现方式?
第一种实现代码
public DataSet SearchName(string LastName, string FirstName, DateTime DateOfBirth) { try { using (SqlConnection con = new SqlConnection(Properties.Settings.Default.DBPreTrial)) { using (SqlCommand cmd = new SqlCommand()) { cmd.CommandText = "spSearchName"; cmd.CommandType = CommandType.StoredProcedure; cmd.Connection = con; cmd.Parameters.AddWithValue("@LastName", LastName); cmd.Parameters.AddWithValue("@FirstName", FirstName); cmd.Parameters.AddWithValue("@DateOfBirth", DateOfBirth); using (SqlDataAdapter da = new SqlDataAdapter(cmd)) { DataSet dtDocData = new DataSet(); da.Fill(dtDocData); return dtDocData; } } } } catch (Exception ex) { throw new FaultException("Exception - SearchName: " + LastName + ", " + FirstName + ", " + Convert.ToString(DateOfBirth) + " : " + ex.Message); } }
第二种实现代码
public DataSet SearchName(string LastName, string FirstName, DateTime DateOfBirth) { DataSet dtDocData = new DataSet(); try { using (SqlConnection con = new SqlConnection(Properties.Settings.Default.DBPreTrial)) { using (SqlCommand cmd = new SqlCommand()) { cmd.CommandText = "spSearchName"; cmd.CommandType = CommandType.StoredProcedure; cmd.Connection = con; cmd.Parameters.AddWithValue("@LastName", LastName); cmd.Parameters.AddWithValue("@FirstName", FirstName); cmd.Parameters.AddWithValue("@DateOfBirth", DateOfBirth); using (SqlDataAdapter da = new SqlDataAdapter(cmd)) { da.Fill(dtDocData); } } } return dtDocData; } catch (Exception ex) { throw new FaultException("Exception - SearchName: " + LastName + ", " + FirstName + ", " + Convert.ToString(DateOfBirth) + " : " + ex.Message); } if (dtDocData != null) { dtDocData.Dispose(); } }
分析结论
第一种实现是完全合适且推荐的
SqlConnection、SqlCommand、SqlDataAdapter都实现了IDisposable接口,using语句能确保这些对象在代码块结束时自动调用Dispose(),及时释放数据库连接等非托管资源,从根源避免资源泄漏问题。DataSet是在SqlDataAdapter的using块内创建并填充,填充完成后直接返回。这里不用担心DataSet被提前释放:DataSet属于纯托管对象,虽然它实现了IDisposable接口,但内部没有需要手动清理的非托管资源;而且返回后调用方会持有该对象的引用,不会被GC随意回收。- 代码结构紧凑,逻辑清晰,没有冗余代码。
第二种实现存在冗余问题,不推荐
- 方法末尾的
if (dtDocData != null) { dtDocData.Dispose(); }代码永远不会执行:try块要么正常返回dtDocData,要么catch块抛出异常直接跳出方法,程序流程根本走不到这段代码。 DataSet提前在方法开头创建属于不必要的操作,反而分散了代码逻辑。- 虽然它也用
using处理了数据库相关对象,但后续的冗余代码属于画蛇添足,没有任何实际作用。
- 方法末尾的
总结:第一种实现是正确的资源释放方式,完全满足WCF场景下的需求,不需要采用第二种方式。
内容的提问来源于stack exchange,提问作者Bill
相关产品推荐
相关产品推荐

