IEnumerable和Datareader扩展方法,需要建议

时间:2010-10-18 04:52:45

标签: c#

以下是使用基于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;
    }

}

你们认为这将起作用

1 个答案:

答案 0 :(得分:3)

  

...这个方法有一个bug,因为一旦你调用这个方法并关闭了datareader,下一次调用就会返回一个空的IEnumerable

这不是一个错误,datareaders是只有前向的迭代器,你只能迭代它们一次。如果您需要多次迭代结果,请缓存您返回的IEnumerable。最简单的方法是将其包装在List<T>中,或者您可以使用Rx's MemoizeAll()懒惰地缓存它

相关问题