转换SqlDataReader对象到LINQ表达
当如何使用SqlDataReader
在互联网上的例子看,我发现的东西,如:转换SqlDataReader对象到LINQ表达
var command = new SqlCommand( // initialize with query and connection...
var reader = command.ExecuteReader();
while(reader.Read())
{
var foo = reader["SomeColName"];
// etc
}
我可以使用下面的扩展方法:
public static IEnumerable<IDataReader> ToEnumerable(this IDataReader reader)
{
while (reader.Read())
yield return reader;
}
为了使用linq执行查询?
如果我使用下面的扩展方法会不好?如果我关心性能,我应该使用第一个实现吗?
我看不出您的建议扩展程序如何帮助您,因为您只针对每个读取行获得包含相同实例的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;
}
}
这将返回字典的序列(每行一个词典),其将列名映射到该“单元”中的对象。不幸的是,你失去了类型安全并且造成了内存开销。具体的实施仍然取决于你真正想要达到的目标。就个人而言,我总是只使用列索引而不是名称。
这么说,我认为最好的办法还是使用IDataReader
直接创造波苏斯和使用该POCOS与LINQ:
IEnumerable<string> GetSomeColValue(IDataReader reader)
{
while(reader.Read())
yield return reader.GetString(reader.GetOrdinal("SomeColName"));
}
当然,这是一个缩短的例子。在实际代码中,我会完全读出来自阅读器的所有数据,并在返回任何内容之前将阅读器实例放置在调用ExecuteReader
的方法内。
你只需要投你IEnumerable
到IEnumerable<IDataRecord>
var enumerable = reader.Cast<IDataRecord>();
var col = enumerable.Select(record => record .GetOrdinal("SomeColName"));
我很好奇,这个'IDataReader'的'Cast'扩展名在哪里声明? 'IDataReader'甚至没有声明'GetEnumerator'方法。 –
(Sql | Db)DataReader实现IEnumerable。而Cast
有趣的是,'SqlDataReader'也实现了这一点。从未使用过,MSDN也没有清楚地说明这是否是当前行列的枚举器,或者是否遍历行。我会看看它,并可能在未来使用它(尽管msdn指出循环是可取的,但不是为什么)。 –
我认为表现不会是一个问题在这里,它只是产生一个状态机的产量。除此之外,我建议公开'IDataRecord'而不是'IDataReader'(继承),否则你会暴露'Read'方法(所以用户可以调用该方法并弄乱结果集)。 – Caramiriel