ORMInternalSqlQuery.cs 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. using Ant.Common;
  2. using Ant.Core;
  3. using Ant.Data;
  4. using Ant.Descriptors;
  5. using Ant.Mapper;
  6. using Ant.ORM;
  7. using Ant.Query.Mapping;
  8. using Ant.Utility;
  9. using System;
  10. using System.Collections;
  11. using System.Collections.Generic;
  12. using System.Data;
  13. using System.Diagnostics;
  14. using System.Linq;
  15. using System.Reflection;
  16. using System.Text;
  17. using System.Threading;
  18. namespace Ant.ORM
  19. {
  20. class ORMInternalSqlQuery<T> : IEnumerable<T>, IEnumerable
  21. {
  22. DataAccess db;
  23. string _sql;
  24. DbParam[] _parameters;
  25. public ORMInternalSqlQuery(DataAccess dbContext, string sql, DbParam[] parameters)
  26. {
  27. this.db = dbContext;
  28. this._sql = sql;
  29. this._parameters = parameters;
  30. }
  31. public IEnumerator<T> GetEnumerator()
  32. {
  33. return new QueryEnumerator(this);
  34. }
  35. IEnumerator IEnumerable.GetEnumerator()
  36. {
  37. return this.GetEnumerator();
  38. }
  39. struct QueryEnumerator : IEnumerator<T>
  40. {
  41. ORMInternalSqlQuery<T> _internalSqlQuery;
  42. IDataReader _reader;
  43. IObjectActivator _objectActivator;
  44. T _current;
  45. bool _hasFinished;
  46. bool _disposed;
  47. public QueryEnumerator(ORMInternalSqlQuery<T> internalSqlQuery)
  48. {
  49. this._internalSqlQuery = internalSqlQuery;
  50. this._reader = null;
  51. this._objectActivator = null;
  52. this._current = default(T);
  53. this._hasFinished = false;
  54. this._disposed = false;
  55. }
  56. public T Current { get { return this._current; } }
  57. object IEnumerator.Current { get { return this._current; } }
  58. public bool MoveNext()
  59. {
  60. if (this._hasFinished || this._disposed)
  61. return false;
  62. if (this._reader == null)
  63. {
  64. this.Prepare();
  65. }
  66. if (this._reader.Read())
  67. {
  68. this._current = (T)this._objectActivator.CreateInstance(this._reader);
  69. return true;
  70. }
  71. else
  72. {
  73. this._reader.Close();
  74. this._internalSqlQuery.db.Close();
  75. this._current = default(T);
  76. this._hasFinished = true;
  77. return false;
  78. }
  79. }
  80. public void Dispose()
  81. {
  82. if (this._disposed)
  83. return;
  84. if (this._reader != null)
  85. {
  86. if (!this._reader.IsClosed)
  87. this._reader.Close();
  88. this._reader.Dispose();
  89. this._reader = null;
  90. }
  91. if (!this._hasFinished)
  92. {
  93. this._internalSqlQuery.db.Close();
  94. this._hasFinished = true;
  95. }
  96. this._current = default(T);
  97. this._disposed = true;
  98. }
  99. public void Reset()
  100. {
  101. throw new NotSupportedException();
  102. }
  103. void Prepare()
  104. {
  105. Type type = typeof(T);
  106. if (AntUtils.IsMapType(type))
  107. {
  108. MappingField mf = new MappingField(type, 0);
  109. this._objectActivator = mf.CreateObjectActivator();
  110. this._reader = this._internalSqlQuery.db.ExecuteReader(this._internalSqlQuery._sql, this._internalSqlQuery._parameters, CommandBehavior.Default, CommandType.Text);
  111. return;
  112. }
  113. this._reader = this._internalSqlQuery.db.ExecuteReader(this._internalSqlQuery._sql, this._internalSqlQuery._parameters, CommandBehavior.Default, CommandType.Text);
  114. this._objectActivator = GetObjectActivator(type, this._reader);
  115. }
  116. static ObjectActivator GetObjectActivator(Type type, IDataReader reader)
  117. {
  118. List<CacheInfo> caches;
  119. if (!ObjectActivatorCache.TryGetValue(type, out caches))
  120. {
  121. if (!Monitor.TryEnter(type))
  122. {
  123. return CreateObjectActivator(type, reader);
  124. }
  125. try
  126. {
  127. caches = ObjectActivatorCache.GetOrAdd(type, new List<CacheInfo>(1));
  128. }
  129. finally
  130. {
  131. Monitor.Exit(type);
  132. }
  133. }
  134. CacheInfo cache = TryGetCacheInfoFromList(caches, reader);
  135. if (cache == null)
  136. {
  137. lock (caches)
  138. {
  139. cache = TryGetCacheInfoFromList(caches, reader);
  140. if (cache == null)
  141. {
  142. ObjectActivator activator = CreateObjectActivator(type, reader);
  143. cache = new CacheInfo(activator, reader);
  144. caches.Add(cache);
  145. }
  146. }
  147. }
  148. return cache.ObjectActivator;
  149. }
  150. static ObjectActivator CreateObjectActivator(Type type, IDataReader reader)
  151. {
  152. EntityConstructorDescriptor constructorDescriptor = EntityConstructorDescriptor.GetInstance(type.GetConstructor(Type.EmptyTypes));
  153. EntityMemberMapper mapper = constructorDescriptor.GetEntityMemberMapper();
  154. Func<IDataReader, ReaderOrdinalEnumerator, ObjectActivatorEnumerator, object> instanceCreator = constructorDescriptor.GetInstanceCreator();
  155. List<IValueSetter> memberSetters = PrepareValueSetters(type, reader, mapper);
  156. return new ObjectActivator(instanceCreator, null, null, memberSetters, null);
  157. }
  158. static List<IValueSetter> PrepareValueSetters(Type type, IDataReader reader, EntityMemberMapper mapper)
  159. {
  160. List<IValueSetter> memberSetters = new List<IValueSetter>(reader.FieldCount);
  161. MemberInfo[] properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.SetProperty);
  162. MemberInfo[] fields = type.GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.SetField);
  163. List<MemberInfo> members = new List<MemberInfo>(properties.Length + fields.Length);
  164. members.AddRange(properties);
  165. members.AddRange(fields);
  166. for (int i = 0; i < reader.FieldCount; i++)
  167. {
  168. string name = reader.GetName(i);
  169. var member = members.Where(a => a.Name == name).FirstOrDefault();
  170. if (member == null)
  171. {
  172. member = members.Where(a => string.Equals(a.Name, name, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();
  173. if (member == null)
  174. continue;
  175. }
  176. IMRM mMapper = mapper.GetMemberMapper(member);
  177. if (mMapper == null)
  178. continue;
  179. MappingMemberBinder memberBinder = new MappingMemberBinder(mMapper, i);
  180. memberSetters.Add(memberBinder);
  181. }
  182. return memberSetters;
  183. }
  184. static CacheInfo TryGetCacheInfoFromList(List<CacheInfo> caches, IDataReader reader)
  185. {
  186. CacheInfo cache = null;
  187. for (int i = 0; i < caches.Count; i++)
  188. {
  189. var item = caches[i];
  190. if (item.IsTheSameFields(reader))
  191. {
  192. cache = item;
  193. break;
  194. }
  195. }
  196. return cache;
  197. }
  198. static readonly System.Collections.Concurrent.ConcurrentDictionary<Type, List<CacheInfo>> ObjectActivatorCache = new System.Collections.Concurrent.ConcurrentDictionary<Type, List<CacheInfo>>();
  199. }
  200. public class CacheInfo
  201. {
  202. Tuple<string, Type>[] _readerFields;
  203. ObjectActivator _objectActivator;
  204. public CacheInfo(ObjectActivator activator, IDataReader reader)
  205. {
  206. int fieldCount = reader.FieldCount;
  207. var readerFields = new Tuple<string, Type>[fieldCount];
  208. for (int i = 0; i < fieldCount; i++)
  209. {
  210. readerFields[i] = new Tuple<string, Type>(reader.GetName(i), reader.GetFieldType(i));
  211. }
  212. this._readerFields = readerFields;
  213. this._objectActivator = activator;
  214. }
  215. public ObjectActivator ObjectActivator { get { return this._objectActivator; } }
  216. public bool IsTheSameFields(IDataReader reader)
  217. {
  218. Tuple<string, Type>[] readerFields = this._readerFields;
  219. int fieldCount = reader.FieldCount;
  220. if (fieldCount != readerFields.Length)
  221. return false;
  222. for (int i = 0; i < fieldCount; i++)
  223. {
  224. Tuple<string, Type> tuple = readerFields[i];
  225. if (reader.GetFieldType(i) != tuple.Item2 || reader.GetName(i) != tuple.Item1)
  226. {
  227. return false;
  228. }
  229. }
  230. return true;
  231. }
  232. }
  233. }
  234. }