以下是使用基于OMU值注入器的“DataReaderInjection”类将datareader转换为对象的扩展方法。
public static IEnumerable<T> MapTo<T>(this IDataReader reader) where T : new() {
return reader.MapTo<T>(null);
}
public static IEnumerable<T> MapTo<T>(this IDataReader reader, Action<IDataReader, T> customMappingFunction) where T : new() {
using (reader)
while (!reader.IsClosed && reader.Read()) {
var nextItem = new T();
nextItem.InjectFrom<DataReaderInjection>(reader);
if (customMappingFunction != null)
customMappingFunction(reader, nextItem);
yield return nextItem;
}
}
这个方法有一个bug,因为一旦你调用这个方法并且datareader被关闭,下一个调用将返回一个空的IEnumerable,为了解决这个问题,我将上面的代码更改为以下内容。
public static class DataAccessExtensions
{
public static IEnumerable<T> MapTo<T>(this IDataReader reader) where T : new() {
return reader.MapTo<T>(null);
}
private static Dictionary<int, IEnumerable> dataReaderCache = new Dictionary<int, IEnumerable>();
private static object lockObj = new object();
public static IEnumerable<T> MapTo<T>(this IDataReader reader, Action<IDataReader, T> customMappingFunction) where T : new() {
lock (lockObj)
{
if (dataReaderCache.ContainsKey(reader.GetHashCode()))
return dataReaderCache[reader.GetHashCode()] as IEnumerable<T>;
}
List<T> finalList = new List<T>();
using (reader) {
while (!reader.IsClosed && reader.Read()) {
var nextItem = new T();
nextItem
.InjectFrom<DataReaderInjection>(reader);
if (customMappingFunction != null)
customMappingFunction(reader, nextItem);
finalList.Add(nextItem);
}
}
lock (lockObj)
{
dataReaderCache.Add(reader.GetHashCode(), finalList);
}
return finalList;
}
}
你们认为这将起作用
答案 0 :(得分:3)
...这个方法有一个bug,因为一旦你调用这个方法并关闭了datareader,下一次调用就会返回一个空的IEnumerable
这不是一个错误,datareaders是只有前向的迭代器,你只能迭代它们一次。如果您需要多次迭代结果,请缓存您返回的IEnumerable。最简单的方法是将其包装在List<T>
中,或者您可以使用Rx's MemoizeAll()懒惰地缓存它