如何从SqlConnection对象中“分离”SqlDataReader?

时间:2010-01-18 15:22:45

标签: c# sqldatareader sqlconnection

我有一个返回SqlDataReader的方法(“GetDataReader”,让我们调用它)。它位于Singleton DataFactory类中,用于维护与数据库的持久连接。

这个问题是返回后,DataReader仍然“连接”到我的DataFactory中的Connection对象。所以,我必须确保调用GetDataReader的代码然后在返回的DataReader上调用Close(),否则,它会“锁定”Connection:

  

已经有一个与此命令关联的打开DataReader,必须先关闭它。

在从GetDataReader发回DataReader之前,如何“分离”DataReader?要么是,要么克隆它并发回克隆?我不想让调用代码总是明确地关闭它。

这里必须有一个最好的做法。

更新

感谢大家的意见。最重要的是,我需要失去使用DataReaders并切换到DataTables的习惯。它们更容易管理。

另外,感谢有关连接池的说明。我知道它,但只是没有把两个和两个放在一起,并意识到我正在重新发明轮子。

5 个答案:

答案 0 :(得分:6)

DataReader必须保持与数据库的连接,直到您不再需要它们为止 - 这就是使用DataReader的本质,因此您无法“断开”它们。当您使用完数据阅读器后,您应该将其关闭(.Close()),但之后就不能再使用了它。

从.NET 2.0开始,如果您使用的是SQL 2005或更高版本,则可以按照MARS的说明使用here(多个活动结果集)。这允许您为多个数据读取器使用单个连接,只需更改连接字符串即可。 但是,SqlDataReaders并不适合以您想要的方式传递代码。

或者(我认为您需要这样做),您可能希望使用DataSet / DataTables所在的断开连接的结果集。您使用SqlDataAdapter来填充DataSet / DataTable查询结果。然后,您可以将该连接用于任何其他目的,或关闭连接,它不会影响您的内存中结果集。您可以在代码周围传递结果集,而无需维护开放的数据库连接。

答案 1 :(得分:2)

不要坚持数据库连接。有一个称为“连接池”的功能。获得新的联系并不昂贵。

答案 2 :(得分:1)

通常,最佳做法是使用连接池而不是持久连接,以允许多个用户同时访问。我能想到做你想做的事的唯一方法是从阅读器加载一个DataSet并返回它。

答案 3 :(得分:0)

我认为您可能会将数据集(断开连接的嵌入数据)和数据集(无数据)混淆在一起。没有SqlCnnection的DataReader是......嗯......只是一个Reader,即没有数据; - )

我认为你的问题在于你的思路。我猜你是一个老学校的程序员,常常手工做。在dot net的“托管”世界中,很多东西都是为你管理的; ADO.NET已经有了一个有效的数据连接池系统,你不需要维护自己的池。

-Oisin

答案 4 :(得分:0)

这是一个方便的帮助方法,可以对连接执行某些SQL,并使其与服务器断开连接:

public static DbDataReader ExecuteReaderClient(DbConnection connection, DbTransaction transaction, String commandText)
{
    DbCommand command = connection.CreateCommand();
    command.CommandText = commandText;
    if (transaction != null)
        command.Transaction = transaction;

    DbDataAdapter adapter = DbProviderFactories.GetFactory(connection).CreateDataAdapter();

    adapter.SelectCommand = command;
    DataSet dataset = new DataSet();

    try
    {
        adapter.Fill(dataset);
    }
    catch (Exception e)
    {
        throw new Exception(
                  e.Message + "\r\n" +
                  "Command Text" + "\r\n" +
                  commandText, e);
    }

    try
    {
        return dataset.CreateDataReader();
    }
    finally
    {
        dataset.Dispose();
    }
}