|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182 |
- using System;
- using System.Collections.Generic;
- using System.Data;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
-
- namespace RDH.Data
- {
- public class GridReader : IDisposable
- {
- private IDataReader reader;
- private IDbCommand command;
- private Identity identity;
-
- internal GridReader(IDbCommand command, IDataReader reader, Identity identity)
- {
- this.command = command;
- this.reader = reader;
- this.identity = identity;
- }
- /// <summary>
- /// Read the next grid of results
- /// </summary>
- public IEnumerable<T> Read<T>()
- {
- if (reader == null) throw new ObjectDisposedException(GetType().Name);
- if (consumed) throw new InvalidOperationException("Each grid can only be iterated once");
- var typedIdentity = identity.ForGrid(typeof(T), gridIndex);
- CacheInfo cache = SqlMapper.GetCacheInfo(typedIdentity);
- var deserializer = cache.Deserializer;
-
- Func<Func<IDataReader, object>> deserializerGenerator = () =>
- {
- deserializer = SqlMapper.GetDeserializer(typeof(T), reader, 0, -1, false);
- cache.Deserializer = deserializer;
- return deserializer;
- };
-
- if (deserializer == null)
- {
- deserializer = deserializerGenerator();
- }
- consumed = true;
- return ReadDeferred<T>(gridIndex, deserializer, typedIdentity, deserializerGenerator);
- }
-
- private IEnumerable<TReturn> MultiReadInternal<TFirst, TSecond, TThird, TFourth, TFifth, TSixth,TSeventh,TReturn>(object func, string splitOn)
- {
-
- var identity = this.identity.ForGrid(typeof(TReturn), new Type[] {
- typeof(TFirst),
- typeof(TSecond),
- typeof(TThird),
- typeof(TFourth),
- typeof(TFifth),
- typeof(TSixth),
- typeof(TSeventh)
- }, gridIndex);
- try
- {
- foreach (var r in SqlMapper.MultiMapImpl<TFirst, TSecond, TThird, TFourth, TFifth, TSixth, TSeventh, TReturn>(null, null, func, null, null, splitOn, null, null, reader, identity))
- {
- yield return r;
- }
- }
- finally
- {
- NextResult();
- }
- }
-
- #if CSHARP30
- public IEnumerable<TReturn> Read<TFirst, TSecond, TReturn>(Func<TFirst, TSecond, TReturn> func, string splitOn)
- #else
- public IEnumerable<TReturn> Read<TFirst, TSecond, TReturn>(Func<TFirst, TSecond, TReturn> func, string splitOn = "id")
- #endif
- {
- return MultiReadInternal<TFirst, TSecond, DontMap,DontMap, DontMap, DontMap, DontMap, TReturn>(func, splitOn);
- }
-
- #if CSHARP30
- public IEnumerable<TReturn> Read<TFirst, TSecond, TThird, TReturn>(Func<TFirst, TSecond, TThird, TReturn> func, string splitOn)
- #else
- public IEnumerable<TReturn> Read<TFirst, TSecond, TThird, TReturn>(Func<TFirst, TSecond, TThird, TReturn> func, string splitOn = "id")
- #endif
- {
- return MultiReadInternal<TFirst, TSecond, TThird, DontMap,DontMap, DontMap, DontMap, TReturn>(func, splitOn);
- }
-
- #if CSHARP30
- public IEnumerable<TReturn> Read<TFirst, TSecond, TThird, TFourth, TReturn>(Func<TFirst, TSecond, TThird, TFourth, TReturn> func, string splitOn)
- #else
- public IEnumerable<TReturn> Read<TFirst, TSecond, TThird, TFourth, TReturn>(Func<TFirst, TSecond, TThird, TFourth, TReturn> func, string splitOn = "id")
- #endif
- {
- return MultiReadInternal<TFirst, TSecond, TThird, TFourth, DontMap, DontMap, DontMap, TReturn>(func, splitOn);
- }
-
- #if CSHARP30
- public IEnumerable<TReturn> Read<TFirst, TSecond, TThird, TFourth, TReturn>(Func<TFirst, TSecond, TThird, TFourth, TReturn> func, string splitOn)
- #else
- public IEnumerable<TReturn> Read<TFirst, TSecond, TThird, TFourth, TFifth, TReturn>(Func<TFirst, TSecond, TThird, TFourth, TFifth,TReturn> func, string splitOn = "id")
- #endif
- {
- return MultiReadInternal<TFirst, TSecond, TThird, TFourth, TFifth, DontMap, DontMap, TReturn>(func, splitOn);
- }
-
- #if CSHARP30
- public IEnumerable<TReturn> Read<TFirst, TSecond, TThird, TFourth, TReturn>(Func<TFirst, TSecond, TThird, TFourth, TReturn> func, string splitOn)
- #else
- public IEnumerable<TReturn> Read<TFirst, TSecond, TThird, TFourth, TFifth,TSixth, TReturn>(Func<TFirst, TSecond, TThird, TFourth, TFifth,TSixth, TReturn> func, string splitOn = "id")
- #endif
- {
- return MultiReadInternal<TFirst, TSecond, TThird, TFourth, TFifth, TSixth, DontMap, TReturn>(func, splitOn);
- }
-
-
- #if !CSHARP30
- public IEnumerable<TReturn> Read<TFirst, TSecond, TThird, TFourth, TFifth, TSixth, TSeventh, TReturn>(Func<TFirst, TSecond, TThird, TFourth, TFifth, TSixth, TSeventh, TReturn> func, string splitOn = "id")
- {
- return MultiReadInternal<TFirst, TSecond, TThird, TFourth, TFifth, TSixth, TSeventh, TReturn>(func, splitOn);
- }
- #endif
-
- private IEnumerable<T> ReadDeferred<T>(int index, Func<IDataReader, object> deserializer, Identity typedIdentity, Func<Func<IDataReader, object>> deserializerGenerator)
- {
- try
- {
- while (index == gridIndex && reader.Read())
- {
- object next;
- try
- {
- next = deserializer(reader);
- }
- catch (DataException)
- {
- deserializer = deserializerGenerator();
- next = deserializer(reader);
- }
- yield return (T)next;
- }
- }
- finally // finally so that First etc progresses things even when multiple rows
- {
- if (index == gridIndex)
- {
- NextResult();
- }
- }
- }
- private int gridIndex;
- private bool consumed;
- private void NextResult()
- {
- if (reader.NextResult())
- {
- gridIndex++;
- consumed = false;
- }
- else
- {
- Dispose();
- }
-
- }
- public void Dispose()
- {
- if (reader != null)
- {
- reader.Dispose();
- reader = null;
- }
- if (command != null)
- {
- command.Dispose();
- command = null;
- }
- }
- }
- }
|