使用 SqlDataReader 作为资源的习惯用法
Posted
技术标签:
【中文标题】使用 SqlDataReader 作为资源的习惯用法【英文标题】:Idiom for using SqlDataReader as a resource 【发布时间】:2009-06-30 11:07:32 【问题描述】:继this 问题之后,我发现自己一遍又一遍地编写以下代码:
SqlCommand command = new SqlCommand();
// Code to initialize command with what we want to do
using (SqlConnection connection = openConnection())
command.Connection = connection;
using (SqlDataReader dataReader = thisCommand.ExecuteReader())
while (dataReader.Read())
// Do stuff with results
不得不嵌套两个 using 语句是相当乏味的。有没有办法告诉 SqlDataReader 它拥有命令,并告诉命令它拥有连接?
如果有办法做到这一点,那么我可以编写一个可以像这样调用的辅助方法:
// buildAndExecuteCommand opens the connection, initializes the command
// with the connection and returns the SqlDataReader object. Dispose of the
// SqlDataReader to dispose of all resources that were acquired
using(SqlDataReader reader = buildAndExecuteCommand(...))
// Do stuff with reader
还是我必须硬着头皮在 SqlDataReader 上编写自己的包装器?
【问题讨论】:
其实,上面的SqlCommand也应该在using语句中,所以你会有3个嵌套语句。 【参考方案1】:有一件事是编写一个为您处理的方法,用每个结果回调一个委托。例如:
using (SqlConnection connection = openConnection())
command.Connection = connection;
ExecuteReaderWithCommand(command, reader =>
// Do stuff with the result here.
);
那么 ExecuteReaderWithCommand 会是这样的:
public static void ExecuteReaderWithCommand(SqlCommand command,
Action<SqlDataReader> action)
using (SqlDataReader dataReader = thisCommand.ExecuteReader())
while (reader.Read())
action(reader);
如果您愿意,可以将其作为SqlCommand
的扩展方法。哎呀,如果你愿意,你也可以去城里让它为你打开连接……你越能抽象出“打开/使用/关闭”的概念,越好。
【讨论】:
+1,lambda 是最干净的。我也在想同样的事情,但像往常一样,斯基特先生很快就抽签了:-) 我同意“你越能抽象出“打开/使用/关闭”的概念——这就是 DAAB 在某种程度上所做的。 是的......虽然使用.NET 2.0,但委托语法最终变得非常笨拙。 叹息【参考方案2】:你可以这样写,并告诉dataReader在使用后关闭连接:
SqlCommand command = new SqlCommand();
command.Connection = openConnection();
using (SqlDataReader dataReader = command.ExecuteReader(CommandBehavior.CloseConnection))
while (dataReader.Read())
// Do stuff with results
但是最好显式关闭连接,因为在打开连接和 ExecuteReader 之间可能会发生异常。
【讨论】:
【参考方案3】:您必须自己构建包装器。或者如果可以的话,你可以使用 ORM。
【讨论】:
【参考方案4】:为什么不看看Enterprise Library DAAB?
这是来自documentation 的代码示例,已针对您的场景进行了调整:
Database db = DatabaseFactory.CreateDatabase();
using (IDataReader reader = db.ExecuteReader(CommandType.Text, "SQL here..." ))
while (reader.Read())
action(reader);
【讨论】:
因为 ADO.NET 适合大多数需求,而且通常没有必要在 [还] 另一个库中。 @Arbiter。我从来没有说过使用,我说看看。它解决了这个问题。真正由保罗来决定是否拥有“另一个库”是一个问题。 DAAB 的设计目标之一是防止开发人员重复编写相同的代码。 同意,决定权在作者 :)【参考方案5】:使用诸如 Action
public IDataReader ExecuteReader(string commandText, CommandType commandType,
IDbDataParameter[] parameters)
IDbConnection connection = CreateConnection();
try
IDbCommand command = CreateCommand(commandText, connection);
command.CommandType = commandType;
AppendParameters(command, parameters);
connection.Open();
return command.ExecuteReader(CommandBehavior.CloseConnection);
catch
connection.Close();
throw;
【讨论】:
以上是关于使用 SqlDataReader 作为资源的习惯用法的主要内容,如果未能解决你的问题,请参考以下文章
如何在 SqlDataReader 之前知道或获取数组大小?并将其作为 json 返回
C#-使用SqlDataReader读取过程的输出参数[duplicate]