使用SqlDataReader作为资源的习惯用法

时间:2009-06-30 11:07:33

标签: c# .net sql sql-server

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上编写自己的包装器?

5 个答案:

答案 0 :(得分:7)

有一件事就是编写一个为您处理的方法,使用每个结果回调一个委托。例如:

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 :(得分:1)

您可以编写类似这样的内容,并告诉dataReader在使用后关闭连接:

SqlCommand command = new SqlCommand();
command.Connection = openConnection();
using (SqlDataReader dataReader = command.ExecuteReader(CommandBehavior.CloseConnection))
{
    while (dataReader.Read())
    {
        // Do stuff with results
    }
}

但是,最好显式关闭连接,因为连接打开和ExecuteReader之间可能会发生异常。

答案 2 :(得分:0)

你必须自己构建包装器。或者你可以使用ORM,如果这是一个选项。

答案 3 :(得分:0)

为什么不看Enterprise Library DAAB

以下是来自documentation的代码示例,根据您的方案进行了调整:

Database db = DatabaseFactory.CreateDatabase();

using (IDataReader reader = db.ExecuteReader(CommandType.Text, "SQL here..." ))
{
   while (reader.Read())
    {
        action(reader);
    }
}

答案 4 :(得分:0)

使用Action&lt; T&gt;等委托当然是一个选项,但我使用了一组类似于.NET 1.0以来的重载。调用者使用using块来处理返回的读取器,后者又处理连接。

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;
    }
}