1 //---------------------------------------------------------------------
2 // <copyright file="EntityDataSourceQueryBuilder.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
8 //---------------------------------------------------------------------
10 namespace System.Web.UI.WebControls
12 using System.Collections;
13 using System.ComponentModel;
14 using System.Data.Common;
15 using System.Data.Metadata.Edm;
16 using System.Data.Objects;
17 using System.Diagnostics;
18 using System.Globalization;
21 internal abstract class EntityDataSourceQueryBuilder<T>
23 private readonly DataSourceSelectArguments _arguments;
24 private readonly string _commandText;
25 private readonly ObjectParameter[] _commandParameters;
26 private readonly string _whereExpression;
27 private readonly ObjectParameter[] _whereParameters;
28 private readonly string _entitySetQueryExpression;
29 private readonly OrderByBuilder _orderByBuilder;
30 private string _includePaths;
31 private TypeUsage _resultType;
32 private Nullable<int> _count;
34 protected EntityDataSourceQueryBuilder(DataSourceSelectArguments arguments,
35 string commandText, ObjectParameter[] commandParameters,
36 string whereExpression, ObjectParameter[] whereParameters, string entitySetQueryExpression,
37 string selectExpression, string groupByExpression, ObjectParameter[] selectParameters,
38 OrderByBuilder orderByBuilder,
41 _arguments = arguments;
42 _commandText = commandText;
43 _commandParameters = commandParameters;
44 _whereExpression = whereExpression;
45 _whereParameters = whereParameters;
46 _entitySetQueryExpression = entitySetQueryExpression;
47 _orderByBuilder = orderByBuilder;
48 _includePaths = includePaths;
51 internal delegate EntityDataSourceQueryBuilder<T> Creator(DataSourceSelectArguments arguments,
52 string commandText, ObjectParameter[] commandParameters,
53 string whereExpression, ObjectParameter[] whereParameters, string entitySetQueryExpression,
54 string selectExpression, string groupByExpression, ObjectParameter[] selectParameters,
55 OrderByBuilder orderByBuilder,
58 internal TypeUsage ResultType
62 Debug.Assert(_resultType != null, "ResultType is only valid after Build()");
66 internal int TotalCount
70 Debug.Assert(_count.HasValue, "Count is not valid until after Build. And only then if computeCount is true");
74 internal IEnumerable Execute(ObjectQuery<T> queryT)
76 return (IEnumerable)(((IListSource)(queryT)).GetList());
79 internal ObjectQuery<T> BuildBasicQuery(ObjectContext context, bool computeCount)
81 ObjectQuery<T> queryT = QueryBuilderUtils.ConstructQuery<T>(context, _entitySetQueryExpression, _commandText, _commandParameters);
82 queryT = ApplyWhere(queryT);
83 queryT = ApplySelect(queryT); // Select and/or GroupBy application
84 _resultType = queryT.GetResultType();
88 internal ObjectQuery<T> CompleteBuild(ObjectQuery<T> queryT, ObjectContext context, bool computeCount, bool wasExtended)
92 _count = queryT.Count();
95 queryT = wasExtended ? ApplyQueryableOrderByAndPaging(queryT) : ApplyOrderByAndPaging(queryT);
96 queryT = ApplyIncludePaths(queryT);
101 private ObjectQuery<T> ApplyWhere(ObjectQuery<T> queryT)
103 if (!String.IsNullOrEmpty(_whereExpression))
105 queryT = queryT.Where(_whereExpression, _whereParameters);
110 protected abstract ObjectQuery<T> ApplySelect(ObjectQuery<T> queryT);
112 internal ObjectQuery<T> ApplyOrderBy(ObjectQuery<T> queryT)
114 string orderByClause;
115 ObjectParameter[] orderByParameters;
116 // Apply all possible ordering except the sort expression, because it might only be valid after the query has been extended
117 _orderByBuilder.Generate(_resultType, out orderByClause, out orderByParameters, false /*applySortExpression*/);
119 return String.IsNullOrEmpty(orderByClause) ? queryT : queryT.OrderBy(orderByClause, orderByParameters);
122 private ObjectQuery<T> ApplyOrderByAndPaging(ObjectQuery<T> queryT)
124 // This re-applys the order-by as part of the skip
125 string orderByClause;
126 ObjectParameter[] orderByParameters;
127 _orderByBuilder.Generate(_resultType, out orderByClause, out orderByParameters, true /*applySortExpression*/);
128 bool paging = _arguments.MaximumRows > 0 && _arguments.StartRowIndex >= 0;
129 var hasOrderByClause = !String.IsNullOrEmpty(orderByClause);
133 if (!hasOrderByClause)
135 throw new InvalidOperationException(Strings.EntityDataSourceQueryBuilder_PagingRequiresOrderBy);
137 queryT = queryT.Skip(orderByClause, _arguments.StartRowIndex.ToString(CultureInfo.InvariantCulture), orderByParameters).Top(_arguments.MaximumRows.ToString(CultureInfo.InvariantCulture), QueryBuilderUtils.EmptyObjectParameters);
141 if (hasOrderByClause)
143 queryT = queryT.OrderBy(orderByClause, orderByParameters);
150 private ObjectQuery<T> ApplyQueryableOrderByAndPaging(ObjectQuery<T> queryT)
152 queryT = _orderByBuilder.BuildQueryableOrderBy(queryT) as ObjectQuery<T>;
153 bool paging = _arguments.MaximumRows > 0 && _arguments.StartRowIndex >= 0;
156 queryT = queryT.Skip(_arguments.StartRowIndex).Take(_arguments.MaximumRows) as ObjectQuery<T>;
162 private ObjectQuery<T> ApplyIncludePaths(ObjectQuery<T> objectQuery)
164 if (!string.IsNullOrEmpty(_includePaths))
166 foreach (string include in _includePaths.Split(','))
168 string trimmedInclude = include.Trim();
169 if (!string.IsNullOrEmpty(trimmedInclude))
171 objectQuery = objectQuery.Include(trimmedInclude);
179 internal class EntityDataSourceObjectQueryBuilder<T> : EntityDataSourceQueryBuilder<T>
181 private EntityDataSourceObjectQueryBuilder(DataSourceSelectArguments arguments,
182 string commandText, ObjectParameter[] commandParameters,
183 string whereExpression, ObjectParameter[] whereParameters, string entitySetQueryExpression,
184 string selectExpression, string groupByExpression, ObjectParameter[] selectParameters,
185 OrderByBuilder orderByBuilder,
188 commandText, commandParameters,
189 whereExpression, whereParameters, entitySetQueryExpression,
190 selectExpression, groupByExpression, selectParameters,
196 static internal EntityDataSourceQueryBuilder<T>.Creator GetCreator()
201 static internal EntityDataSourceQueryBuilder<T> Create(DataSourceSelectArguments arguments,
202 string commandText, ObjectParameter[] commandParameters,
203 string whereExpression, ObjectParameter[] whereParameters, string entitySetQueryExpression,
204 string selectExpression, string groupByExpression, ObjectParameter[] selectParameters,
205 OrderByBuilder orderByBuilder,
208 return new EntityDataSourceObjectQueryBuilder<T>(arguments,
209 commandText, commandParameters,
210 whereExpression, whereParameters, entitySetQueryExpression,
211 selectExpression, groupByExpression, selectParameters,
216 protected override ObjectQuery<T> ApplySelect(ObjectQuery<T> queryT)
223 internal class EntityDataSourceRecordQueryBuilder : EntityDataSourceQueryBuilder<DbDataRecord>
225 private readonly string _selectExpression;
226 private readonly string _groupByExpression;
227 private readonly ObjectParameter[] _selectParameters;
229 private EntityDataSourceRecordQueryBuilder(DataSourceSelectArguments arguments,
230 string commandText, ObjectParameter[] commandParameters,
231 string whereExpression, ObjectParameter[] whereParameters, string entitySetQueryExpression,
232 string selectExpression, string groupByExpression, ObjectParameter[] selectParameters,
233 OrderByBuilder orderByBuilder,
236 commandText, commandParameters,
237 whereExpression, whereParameters, entitySetQueryExpression,
238 selectExpression, groupByExpression, selectParameters,
242 _selectExpression = selectExpression;
243 _groupByExpression = groupByExpression;
244 _selectParameters = selectParameters;
247 static internal EntityDataSourceQueryBuilder<DbDataRecord> Create(DataSourceSelectArguments arguments,
248 string commandText, ObjectParameter[] commandParameters,
249 string whereExpression, ObjectParameter[] whereParameters, string entitySetQueryExpression,
250 string selectExpression, string groupByExpression, ObjectParameter[] selectParameters,
251 OrderByBuilder orderByBuilder,
254 return new EntityDataSourceRecordQueryBuilder(arguments,
255 commandText, commandParameters,
256 whereExpression, whereParameters, entitySetQueryExpression,
257 selectExpression, groupByExpression, selectParameters,
262 protected override ObjectQuery<DbDataRecord> ApplySelect(ObjectQuery<DbDataRecord> queryT)
264 Debug.Assert(!String.IsNullOrEmpty(_selectExpression), "Select expression should not be of zero length.");
266 if (!string.IsNullOrEmpty(_groupByExpression))
268 queryT = queryT.GroupBy(_groupByExpression, _selectExpression, _selectParameters);
272 queryT = queryT.Select(_selectExpression, _selectParameters);
278 internal static class QueryBuilderUtils
280 internal static readonly ObjectParameter[] EmptyObjectParameters = new ObjectParameter[] { };
282 internal static ObjectQuery<T> ConstructQuery<T>(ObjectContext context,
283 string entitySetQueryExpression,
285 ObjectParameter[] commandParameters)
287 string queryExpression;
288 ObjectParameter[] queryParameters;
289 if (!string.IsNullOrEmpty(commandText))
291 queryExpression = commandText;
292 queryParameters = commandParameters;
296 queryExpression = entitySetQueryExpression;
297 queryParameters = QueryBuilderUtils.EmptyObjectParameters;
300 return context.CreateQuery<T>(queryExpression, queryParameters);