PageRenderTime 24ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 0ms

/mcs/class/System.Data.Linq/src/DbLinq/Data/Linq/Implementation/QueryProvider.cs

https://github.com/ekovalenko-softheme/mono
C# | 239 lines | 114 code | 17 blank | 108 comment | 9 complexity | 0ab41400f16e8cb736a75e214f148930 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, CC-BY-SA-3.0, GPL-2.0, Unlicense
  1. #region MIT license
  2. //
  3. // MIT license
  4. //
  5. // Copyright (c) 2007-2008 Jiri Moudry, Pascal Craponne
  6. //
  7. // Permission is hereby granted, free of charge, to any person obtaining a copy
  8. // of this software and associated documentation files (the "Software"), to deal
  9. // in the Software without restriction, including without limitation the rights
  10. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11. // copies of the Software, and to permit persons to whom the Software is
  12. // furnished to do so, subject to the following conditions:
  13. //
  14. // The above copyright notice and this permission notice shall be included in
  15. // all copies or substantial portions of the Software.
  16. //
  17. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  20. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  23. // THE SOFTWARE.
  24. //
  25. #endregion
  26. using System;
  27. using System.Collections;
  28. using System.Collections.Generic;
  29. using System.Linq;
  30. using System.Linq.Expressions;
  31. using DbLinq.Data.Linq.Sugar;
  32. using DbLinq.Util;
  33. #if MONO_STRICT
  34. using System.Data.Linq;
  35. #else
  36. using DbLinq.Data.Linq;
  37. #endif
  38. namespace DbLinq.Data.Linq.Implementation
  39. {
  40. /// <summary>
  41. /// QueryProvider is used by both DataContext and Table
  42. /// to build queries
  43. /// It is split is two parts (non-generic and generic) for copy reasons
  44. /// </summary>
  45. internal abstract class QueryProvider
  46. {
  47. /// <summary>
  48. /// Gets or sets the expression chain.
  49. /// </summary>
  50. /// <value>The expression chain.</value>
  51. public ExpressionChain ExpressionChain { get; set; }
  52. /// <summary>
  53. /// Gets or sets the type of the table.
  54. /// </summary>
  55. /// <value>The type of the table.</value>
  56. public Type TableType { get; set; }
  57. /// <summary>
  58. /// Gets the query.
  59. /// </summary>
  60. /// <param name="expression">The expression.</param>
  61. /// <returns></returns>
  62. public abstract SelectQuery GetQuery(Expression expression);
  63. }
  64. /// <summary>
  65. /// QueryProvider, generic version
  66. /// </summary>
  67. /// <typeparam name="T"></typeparam>
  68. internal class QueryProvider<T> : QueryProvider, IQueryProvider, IQueryable<T>, IOrderedQueryable<T>
  69. {
  70. /// <summary>
  71. /// Holder current datancontext
  72. /// </summary>
  73. protected readonly DataContext _dataContext;
  74. /// <summary>
  75. /// Initializes a new instance of the <see cref="QueryProvider&lt;T&gt;"/> class.
  76. /// </summary>
  77. /// <param name="dataContext">The data context.</param>
  78. public QueryProvider(DataContext dataContext)
  79. {
  80. _dataContext = dataContext;
  81. TableType = typeof(T);
  82. ExpressionChain = new ExpressionChain();
  83. }
  84. /// <summary>
  85. /// Initializes a new instance of the <see cref="QueryProvider&lt;T&gt;"/> class.
  86. /// </summary>
  87. /// <param name="tableType">Type of the table.</param>
  88. /// <param name="dataContext">The data context.</param>
  89. /// <param name="expressionChain">The expression chain.</param>
  90. /// <param name="expression">The expression.</param>
  91. public QueryProvider(Type tableType, DataContext dataContext, ExpressionChain expressionChain, Expression expression)
  92. {
  93. _dataContext = dataContext;
  94. TableType = tableType;
  95. ExpressionChain = new ExpressionChain(expressionChain, expression);
  96. }
  97. /// <summary>
  98. /// Creates the query.
  99. /// </summary>
  100. /// <typeparam name="S"></typeparam>
  101. /// <param name="t">The t.</param>
  102. /// <param name="tableType">Type of the table.</param>
  103. /// <param name="dataContext">The data context.</param>
  104. /// <param name="expressionChain">The expression chain.</param>
  105. /// <param name="expression">The expression.</param>
  106. /// <returns></returns>
  107. protected S CreateQuery<S>(Type t, Type tableType, DataContext dataContext, ExpressionChain expressionChain, Expression expression)
  108. {
  109. // no way to work differently
  110. var typedQueryProviderType = typeof(QueryProvider<>).MakeGenericType(t);
  111. var queryProvider = (S)Activator.CreateInstance(typedQueryProviderType, tableType, dataContext,
  112. expressionChain, expression);
  113. return queryProvider;
  114. }
  115. /// <summary>
  116. /// Builds the query, given a LINQ expression
  117. /// </summary>
  118. /// <param name="expression"></param>
  119. /// <returns></returns>
  120. public IQueryable CreateQuery(Expression expression)
  121. {
  122. var type = expression.Type;
  123. if (!type.IsGenericType)
  124. throw Error.BadArgument("S0066: Don't know how to handle non-generic type '{0}'", type);
  125. var genericType = type.GetGenericTypeDefinition();
  126. if (genericType == typeof(IQueryable<>) || genericType == typeof(IOrderedQueryable<>))
  127. type = type.GetGenericArguments()[0];
  128. else
  129. Error.BadArgument("S0068: Don't know how to handle type '{0}'", type);
  130. return CreateQuery<IQueryable>(type, TableType, _dataContext, ExpressionChain, expression);
  131. }
  132. /// <summary>
  133. /// Creates the query.
  134. /// </summary>
  135. /// <typeparam name="TElement">The type of the element.</typeparam>
  136. /// <param name="expression">The expression.</param>
  137. /// <returns></returns>
  138. public IQueryable<TElement> CreateQuery<TElement>(Expression expression)
  139. {
  140. Profiler.At("START QueryProvider.CreateQuery<{0}>({1})", typeof(TElement).Name, expression.ToString());
  141. var query = new QueryProvider<TElement>(TableType, _dataContext, ExpressionChain, expression);
  142. Profiler.At("END QueryProvider.CreateQuery<{0}>(...)", typeof(TElement).Name);
  143. return query;
  144. }
  145. /// <summary>
  146. /// Gets the query.
  147. /// </summary>
  148. /// <param name="expression">The expression.</param>
  149. /// <returns></returns>
  150. public override SelectQuery GetQuery(Expression expression)
  151. {
  152. var expressionChain = ExpressionChain;
  153. if (expression != null)
  154. expressionChain = new ExpressionChain(expressionChain, expression);
  155. return _dataContext.QueryBuilder.GetSelectQuery(expressionChain, new QueryContext(_dataContext));
  156. }
  157. /// <summary>
  158. /// Runs query
  159. /// </summary>
  160. /// <param name="expression"></param>
  161. /// <returns></returns>
  162. public object Execute(Expression expression)
  163. {
  164. return this.GetType()
  165. .GetMethods()
  166. .Where(m => m.Name == "Execute" && m.IsGenericMethod)
  167. .Single()
  168. .MakeGenericMethod(new Type[] { expression.Type })
  169. .Invoke(this, new object[] { expression });
  170. }
  171. /// <summary>
  172. /// Runs query
  173. /// </summary>
  174. /// <typeparam name="TResult"></typeparam>
  175. /// <param name="expression"></param>
  176. /// <returns></returns>
  177. public TResult Execute<TResult>(Expression expression)
  178. {
  179. Profiler.At("START QueryProvider.Execute<{0}>(): Executing expression...", typeof(TResult).Name);
  180. var query = GetQuery(expression);
  181. var result = _dataContext.QueryRunner.SelectScalar<TResult>(query);
  182. Profiler.At("END QueryProvider.Execute<{0}>(): Executing expression...", typeof(TResult).Name);
  183. return result;
  184. }
  185. /// <summary>
  186. /// Enumerates all query items
  187. /// </summary>
  188. /// <returns></returns>
  189. IEnumerator IEnumerable.GetEnumerator()
  190. {
  191. var enumerator = GetEnumerator();
  192. return enumerator;
  193. }
  194. /// <summary>
  195. /// Enumerates all query items
  196. /// </summary>
  197. /// <returns></returns>
  198. public IEnumerator<T> GetEnumerator()
  199. {
  200. Profiler.At("START QueryProvider.GetEnumerator<{0}>(): Executing expression...", typeof(T).Name);
  201. var query = GetQuery(null);
  202. var enumerator = _dataContext.QueryRunner.Select<T>(query).GetEnumerator();
  203. Profiler.At("END QueryProvider.GetEnumerator<{0}>(): Executing expression...", typeof(T).Name);
  204. return enumerator;
  205. }
  206. /// <summary>
  207. /// Returns this QueryProvider as an exception
  208. /// </summary>
  209. public Expression Expression
  210. {
  211. get { return Expression.Constant(this); }
  212. }
  213. public Type ElementType
  214. {
  215. get { return (typeof(T)); }
  216. }
  217. public IQueryProvider Provider
  218. {
  219. get { return this; }
  220. }
  221. }
  222. }