将SqlDataReader转换为linq表达式

Ton*_*Nam 4 c# linq performance sqldatareader

在互联网上查看如何使用的示例时,SqlDataReader我发现了以下内容:

var command = new SqlCommand(  // initialize with query and connection...
var reader = command.ExecuteReader();

while(reader.Read())
{
    var foo = reader["SomeColName"];
    // etc
}
Run Code Online (Sandbox Code Playgroud)

我可以使用以下扩展方法:

public static IEnumerable<IDataReader> ToEnumerable(this IDataReader reader)
{
     while (reader.Read())            
         yield return reader;            
}  
Run Code Online (Sandbox Code Playgroud)

为了使用linq执行查询?

如果我使用以下扩展方法会不好?如果我关心性能,我应该使用第一个实现吗?

Kal*_*ten 11

你只需要投你IEnumerableIEnumerable<IDataRecord>

var enumerable = reader.Cast<IDataRecord>();
var col = enumerable.Select(record => record .GetOrdinal("SomeColName"));
Run Code Online (Sandbox Code Playgroud)


Ren*_*ogt 3

我看不出您提出的扩展对您有什么帮助,因为您只得到一个包含每个读取行的相同实例的IDataReader枚举。

我不确定是否有任何IDataReader与 LINQ 结合的好方法,但您可能想要这样的东西:

public static IEnumerable<Dictionary<string, object>> ToEnumerable(this IDataReader reader)
{
    while (reader.Read())
    {
        Dictionary<string, object> result = new Dictionary<string, object>();
        for (int column = 0; column < reader.FieldCount; column++)
            result.Add(reader.GetName(column), reader.GetValue(column));
        yield return result;
    }
} 
Run Code Online (Sandbox Code Playgroud)

这将返回一系列字典(每行一个字典),它将列名称映射到该“单元格”中的对象。

不幸的是,您会失去类型安全并产生内存开销。具体实现还是取决于你真正想要实现的目标。就我个人而言,我总是只使用列索引而不是名称。


也就是说,我认为最好的方法仍然是IDataReader直接使用创建 pocos 并将此 pocos 与 LINQ 结合使用:

IEnumerable<string> GetSomeColValue(IDataReader reader)
{
    while(reader.Read())
        yield return reader.GetString(reader.GetOrdinal("SomeColName"));
}
Run Code Online (Sandbox Code Playgroud)

当然,这是一个简短的示例。在实际代码中,我会完全读出读取器中的所有数据,并在返回任何内容之前调用的方法内ExecuteReader关闭/处置读取器实例。