如何在c#中编写一个从查询字符串创建DataReader的辅助方法?

时间:2013-08-21 08:38:37

标签: c# ado.net connection-pooling design-patterns

我想创建一个辅助方法,它接受一个sql查询作为参数并返回一个DataReader。

我写了类似的东西:

private IDataReader GetReader(String query)
{
    try
    {
        var connection = dbProvider.CreateConnection();
        var command = dbProvider.CreateCommand();
        command.CommandText = query;
        command.Connection = connection;
        command.Connection.Open();
        return command.ExecuteReader();
    }
    catch (Exception ex)
    {
        ...
    }
}

客户端代码如下所示:

public List<FileGroupDetail> LoadGroupDetail()
{
    String query = ...;

    using (IDataReader reader = GetReader(query))
    {
        return reader.Select(...);
    }
}

尽管在所有客户端调用中都使用了using语句,但我遇到了与连接池相关的问题(超时,传输级错误......)

我的下一步是添加GetReader的重载,该重载接受连接作为参数。这是一个好习惯还是有更好的模式?

1 个答案:

答案 0 :(得分:2)

目前,该连接尚未关闭;您可以通过告诉读者拥有连接(CommandBehavior.CloseConnection,传递给ExecuteReader)来解决这个问题 - 但这只会解决池饱和问题。如果实际问题是次优/过长查询,则不能做太多。但是,我会非常担心:

  • 此设计不允许参数化
  • 这种设计希望人们与读者合作,这可能不是最佳的

传递连接并保持呼叫者连接的所有权,IMO将更清洁,更清晰,但是当你这样做时,你可能想看看像“dapper”这样的工具“,它非常优雅地解决了很多问题,例如:

string region = "North";
using(var conn = dbProvider.CreateConnection()) {
    return conn.Query<Custom>(
        "select * from Customers where Region=@region",
        new { region } // full parameterization, the easy way
    ).ToList(); // Query<T> returns IEnumerable<T>, ideal for LINQ-to-Objects
}