电子药箱通讯服务端
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

GridReader.cs 6.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Data;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Threading.Tasks;
  7. namespace RDH.Data
  8. {
  9. public class GridReader : IDisposable
  10. {
  11. private IDataReader reader;
  12. private IDbCommand command;
  13. private Identity identity;
  14. internal GridReader(IDbCommand command, IDataReader reader, Identity identity)
  15. {
  16. this.command = command;
  17. this.reader = reader;
  18. this.identity = identity;
  19. }
  20. /// <summary>
  21. /// Read the next grid of results
  22. /// </summary>
  23. public IEnumerable<T> Read<T>()
  24. {
  25. if (reader == null) throw new ObjectDisposedException(GetType().Name);
  26. if (consumed) throw new InvalidOperationException("Each grid can only be iterated once");
  27. var typedIdentity = identity.ForGrid(typeof(T), gridIndex);
  28. CacheInfo cache = SqlMapper.GetCacheInfo(typedIdentity);
  29. var deserializer = cache.Deserializer;
  30. Func<Func<IDataReader, object>> deserializerGenerator = () =>
  31. {
  32. deserializer = SqlMapper.GetDeserializer(typeof(T), reader, 0, -1, false);
  33. cache.Deserializer = deserializer;
  34. return deserializer;
  35. };
  36. if (deserializer == null)
  37. {
  38. deserializer = deserializerGenerator();
  39. }
  40. consumed = true;
  41. return ReadDeferred<T>(gridIndex, deserializer, typedIdentity, deserializerGenerator);
  42. }
  43. private IEnumerable<TReturn> MultiReadInternal<TFirst, TSecond, TThird, TFourth, TFifth, TSixth,TSeventh,TReturn>(object func, string splitOn)
  44. {
  45. var identity = this.identity.ForGrid(typeof(TReturn), new Type[] {
  46. typeof(TFirst),
  47. typeof(TSecond),
  48. typeof(TThird),
  49. typeof(TFourth),
  50. typeof(TFifth),
  51. typeof(TSixth),
  52. typeof(TSeventh)
  53. }, gridIndex);
  54. try
  55. {
  56. foreach (var r in SqlMapper.MultiMapImpl<TFirst, TSecond, TThird, TFourth, TFifth, TSixth, TSeventh, TReturn>(null, null, func, null, null, splitOn, null, null, reader, identity))
  57. {
  58. yield return r;
  59. }
  60. }
  61. finally
  62. {
  63. NextResult();
  64. }
  65. }
  66. #if CSHARP30
  67. public IEnumerable<TReturn> Read<TFirst, TSecond, TReturn>(Func<TFirst, TSecond, TReturn> func, string splitOn)
  68. #else
  69. public IEnumerable<TReturn> Read<TFirst, TSecond, TReturn>(Func<TFirst, TSecond, TReturn> func, string splitOn = "id")
  70. #endif
  71. {
  72. return MultiReadInternal<TFirst, TSecond, DontMap,DontMap, DontMap, DontMap, DontMap, TReturn>(func, splitOn);
  73. }
  74. #if CSHARP30
  75. public IEnumerable<TReturn> Read<TFirst, TSecond, TThird, TReturn>(Func<TFirst, TSecond, TThird, TReturn> func, string splitOn)
  76. #else
  77. public IEnumerable<TReturn> Read<TFirst, TSecond, TThird, TReturn>(Func<TFirst, TSecond, TThird, TReturn> func, string splitOn = "id")
  78. #endif
  79. {
  80. return MultiReadInternal<TFirst, TSecond, TThird, DontMap,DontMap, DontMap, DontMap, TReturn>(func, splitOn);
  81. }
  82. #if CSHARP30
  83. public IEnumerable<TReturn> Read<TFirst, TSecond, TThird, TFourth, TReturn>(Func<TFirst, TSecond, TThird, TFourth, TReturn> func, string splitOn)
  84. #else
  85. public IEnumerable<TReturn> Read<TFirst, TSecond, TThird, TFourth, TReturn>(Func<TFirst, TSecond, TThird, TFourth, TReturn> func, string splitOn = "id")
  86. #endif
  87. {
  88. return MultiReadInternal<TFirst, TSecond, TThird, TFourth, DontMap, DontMap, DontMap, TReturn>(func, splitOn);
  89. }
  90. #if CSHARP30
  91. public IEnumerable<TReturn> Read<TFirst, TSecond, TThird, TFourth, TReturn>(Func<TFirst, TSecond, TThird, TFourth, TReturn> func, string splitOn)
  92. #else
  93. public IEnumerable<TReturn> Read<TFirst, TSecond, TThird, TFourth, TFifth, TReturn>(Func<TFirst, TSecond, TThird, TFourth, TFifth,TReturn> func, string splitOn = "id")
  94. #endif
  95. {
  96. return MultiReadInternal<TFirst, TSecond, TThird, TFourth, TFifth, DontMap, DontMap, TReturn>(func, splitOn);
  97. }
  98. #if CSHARP30
  99. public IEnumerable<TReturn> Read<TFirst, TSecond, TThird, TFourth, TReturn>(Func<TFirst, TSecond, TThird, TFourth, TReturn> func, string splitOn)
  100. #else
  101. public IEnumerable<TReturn> Read<TFirst, TSecond, TThird, TFourth, TFifth,TSixth, TReturn>(Func<TFirst, TSecond, TThird, TFourth, TFifth,TSixth, TReturn> func, string splitOn = "id")
  102. #endif
  103. {
  104. return MultiReadInternal<TFirst, TSecond, TThird, TFourth, TFifth, TSixth, DontMap, TReturn>(func, splitOn);
  105. }
  106. #if !CSHARP30
  107. 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")
  108. {
  109. return MultiReadInternal<TFirst, TSecond, TThird, TFourth, TFifth, TSixth, TSeventh, TReturn>(func, splitOn);
  110. }
  111. #endif
  112. private IEnumerable<T> ReadDeferred<T>(int index, Func<IDataReader, object> deserializer, Identity typedIdentity, Func<Func<IDataReader, object>> deserializerGenerator)
  113. {
  114. try
  115. {
  116. while (index == gridIndex && reader.Read())
  117. {
  118. object next;
  119. try
  120. {
  121. next = deserializer(reader);
  122. }
  123. catch (DataException)
  124. {
  125. deserializer = deserializerGenerator();
  126. next = deserializer(reader);
  127. }
  128. yield return (T)next;
  129. }
  130. }
  131. finally // finally so that First etc progresses things even when multiple rows
  132. {
  133. if (index == gridIndex)
  134. {
  135. NextResult();
  136. }
  137. }
  138. }
  139. private int gridIndex;
  140. private bool consumed;
  141. private void NextResult()
  142. {
  143. if (reader.NextResult())
  144. {
  145. gridIndex++;
  146. consumed = false;
  147. }
  148. else
  149. {
  150. Dispose();
  151. }
  152. }
  153. public void Dispose()
  154. {
  155. if (reader != null)
  156. {
  157. reader.Dispose();
  158. reader = null;
  159. }
  160. if (command != null)
  161. {
  162. command.Dispose();
  163. command = null;
  164. }
  165. }
  166. }
  167. }