annotate Source/Data/Linq/Builder/GroupByBuilder.cs @ 6:11b6da379593

Исправлена странная ошибка при использовании OfType<...>().Where(...)
author cin
date Mon, 05 Dec 2016 05:50:52 +0300
parents f990fcb411a9
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1 using System;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2 using System.Collections;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
3 using System.Collections.Generic;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
4 using System.Data;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
5 using System.Linq;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
6 using System.Linq.Expressions;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
7 using System.Reflection;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
8
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
9 namespace BLToolkit.Data.Linq.Builder
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
10 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
11 using BLToolkit.Linq;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
12 using Data.Sql;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
13
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
14 class GroupByBuilder : MethodCallBuilder
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
15 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
16 #region Builder Methods
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
17
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
18 protected override bool CanBuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
19 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
20 if (!methodCall.IsQueryable("GroupBy"))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
21 return false;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
22
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
23 var body = ((LambdaExpression)methodCall.Arguments[1].Unwrap()).Body.Unwrap();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
24
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
25 if (body.NodeType == ExpressionType.MemberInit)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
26 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
27 var mi = (MemberInitExpression)body;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
28 bool throwExpr;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
29
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
30 if (mi.NewExpression.Arguments.Count > 0 || mi.Bindings.Count == 0)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
31 throwExpr = true;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
32 else
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
33 throwExpr = mi.Bindings.Any(b => b.BindingType != MemberBindingType.Assignment);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
34
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
35 if (throwExpr)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
36 throw new NotSupportedException(string.Format("Explicit construction of entity type '{0}' in group by is not allowed.", body.Type));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
37 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
38
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
39 return (methodCall.Arguments[methodCall.Arguments.Count - 1].Unwrap().NodeType == ExpressionType.Lambda);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
40 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
41
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
42 protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
43 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
44 var sequenceExpr = methodCall.Arguments[0];
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
45 var sequence = builder.BuildSequence(new BuildInfo(buildInfo, sequenceExpr));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
46 var groupingType = methodCall.Type.GetGenericArguments()[0];
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
47 var keySelector = (LambdaExpression)methodCall.Arguments[1].Unwrap();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
48 var elementSelector = (LambdaExpression)methodCall.Arguments[2].Unwrap();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
49
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
50 if (methodCall.Arguments[0].NodeType == ExpressionType.Call)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
51 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
52 var call = (MethodCallExpression)methodCall.Arguments[0];
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
53
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
54 if (call.Method.Name == "Select")
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
55 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
56 var type = ((LambdaExpression)call.Arguments[1].Unwrap()).Body.Type;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
57
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
58 if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(ExpressionBuilder.GroupSubQuery<,>))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
59 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
60 sequence = new SubQueryContext(sequence);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
61 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
62 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
63 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
64
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
65 var key = new KeyContext(buildInfo.Parent, keySelector, sequence);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
66 var groupSql = builder.ConvertExpressions(key, keySelector.Body.Unwrap(), ConvertFlags.Key);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
67
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
68 if (sequence.SqlQuery.Select.IsDistinct ||
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
69 sequence.SqlQuery.GroupBy.Items.Count > 0 ||
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
70 groupSql.Any(_ => !(_.Sql is SqlField || _.Sql is SqlQuery.Column)))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
71 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
72 sequence = new SubQueryContext(sequence);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
73 key = new KeyContext(buildInfo.Parent, keySelector, sequence);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
74 groupSql = builder.ConvertExpressions(key, keySelector.Body.Unwrap(), ConvertFlags.Key);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
75 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
76
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
77 //sequence.SqlQuery.GroupBy.Items.Clear();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
78
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
79 foreach (var sql in groupSql)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
80 sequence.SqlQuery.GroupBy.Expr(sql.Sql);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
81
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
82 new QueryVisitor().Visit(sequence.SqlQuery.From, e =>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
83 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
84 if (e.ElementType == QueryElementType.JoinedTable)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
85 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
86 var jt = (SqlQuery.JoinedTable)e;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
87 if (jt.JoinType == SqlQuery.JoinType.Inner)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
88 jt.IsWeak = false;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
89 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
90 });
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
91
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
92 var element = new SelectContext (buildInfo.Parent, elementSelector, sequence/*, key*/);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
93 var groupBy = new GroupByContext(buildInfo.Parent, sequenceExpr, groupingType, sequence, key, element);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
94
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
95 return groupBy;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
96 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
97
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
98 protected override SequenceConvertInfo Convert(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
99 ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo, ParameterExpression param)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
100 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
101 return null;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
102 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
103
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
104 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
105
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
106 #region KeyContext
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
107
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
108 internal class KeyContext : SelectContext
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
109 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
110 public KeyContext(IBuildContext parent, LambdaExpression lambda, params IBuildContext[] sequences)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
111 : base(parent, lambda, sequences)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
112 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
113 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
114 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
115
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
116 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
117
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
118 #region GroupByContext
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
119
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
120 internal class GroupByContext : SequenceContextBase
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
121 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
122 public GroupByContext(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
123 IBuildContext parent,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
124 Expression sequenceExpr,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
125 Type groupingType,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
126 IBuildContext sequence,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
127 KeyContext key,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
128 SelectContext element)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
129 : base(parent, sequence, null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
130 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
131 _sequenceExpr = sequenceExpr;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
132 _key = key;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
133 _element = element;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
134 _groupingType = groupingType;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
135
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
136 key.Parent = this;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
137 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
138
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
139 readonly Expression _sequenceExpr;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
140 readonly KeyContext _key;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
141 readonly SelectContext _element;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
142 readonly Type _groupingType;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
143
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
144 internal class Grouping<TKey,TElement> : IGrouping<TKey,TElement>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
145 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
146 public Grouping(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
147 TKey key,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
148 QueryContext queryContext,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
149 List<ParameterAccessor> parameters,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
150 Func<IDataContext,TKey,object[],IQueryable<TElement>> itemReader)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
151 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
152 Key = key;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
153
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
154 _queryContext = queryContext;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
155 _parameters = parameters;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
156 _itemReader = itemReader;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
157
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
158 if (Common.Configuration.Linq.PreloadGroups)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
159 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
160 _items = GetItems();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
161 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
162 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
163
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
164 private IList<TElement> _items;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
165 readonly QueryContext _queryContext;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
166 readonly List<ParameterAccessor> _parameters;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
167 readonly Func<IDataContext,TKey,object[],IQueryable<TElement>> _itemReader;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
168
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
169 public TKey Key { get; private set; }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
170
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
171 List<TElement> GetItems()
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
172 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
173 var db = _queryContext.GetDataContext();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
174
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
175 try
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
176 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
177 var ps = new object[_parameters.Count];
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
178
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
179 for (var i = 0; i < ps.Length; i++)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
180 ps[i] = _parameters[i].Accessor(_queryContext.Expression, _queryContext.CompiledParameters);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
181
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
182 return _itemReader(db.DataContextInfo.DataContext, Key, ps).ToList();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
183 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
184 finally
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
185 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
186 _queryContext.ReleaseDataContext(db);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
187 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
188 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
189
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
190 public IEnumerator<TElement> GetEnumerator()
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
191 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
192 if (_items == null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
193 _items = GetItems();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
194
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
195 return _items.GetEnumerator();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
196 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
197
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
198 IEnumerator IEnumerable.GetEnumerator()
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
199 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
200 return GetEnumerator();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
201 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
202 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
203
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
204 interface IGroupByHelper
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
205 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
206 Expression GetGrouping(GroupByContext context);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
207 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
208
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
209 class GroupByHelper<TKey,TElement,TSource> : IGroupByHelper
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
210 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
211 public Expression GetGrouping(GroupByContext context)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
212 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
213 var parameters = context.Builder.CurrentSqlParameters
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
214 .Select((p,i) => new { p, i })
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
215 .ToDictionary(_ => _.p.Expression, _ => _.i);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
216 var paramArray = Expression.Parameter(typeof(object[]), "ps");
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
217
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
218 var groupExpression = context._sequenceExpr.Convert(e =>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
219 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
220 int idx;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
221
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
222 if (parameters.TryGetValue(e, out idx))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
223 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
224 return
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
225 Expression.Convert(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
226 Expression.ArrayIndex(paramArray, Expression.Constant(idx)),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
227 e.Type);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
228 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
229
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
230 return e;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
231 });
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
232
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
233 var keyParam = Expression.Parameter(typeof(TKey), "key");
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
234
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
235 // ReSharper disable AssignNullToNotNullAttribute
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
236
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
237 var expr = Expression.Call(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
238 null,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
239 ReflectionHelper.Expressor<object>.MethodExpressor(_ => Queryable.Where(null, (Expression<Func<TSource,bool>>)null)),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
240 groupExpression,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
241 Expression.Lambda<Func<TSource,bool>>(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
242 Expression.Equal(context._key.Lambda.Body, keyParam),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
243 new[] { context._key.Lambda.Parameters[0] }));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
244
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
245 expr = Expression.Call(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
246 null,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
247 ReflectionHelper.Expressor<object>.MethodExpressor(_ => Queryable.Select(null, (Expression<Func<TSource,TElement>>)null)),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
248 expr,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
249 context._element.Lambda);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
250
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
251 // ReSharper restore AssignNullToNotNullAttribute
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
252
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
253 var lambda = Expression.Lambda<Func<IDataContext,TKey,object[],IQueryable<TElement>>>(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
254 Expression.Convert(expr, typeof(IQueryable<TElement>)),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
255 Expression.Parameter(typeof(IDataContext), "ctx"),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
256 keyParam,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
257 paramArray);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
258
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
259 var itemReader = CompiledQuery.Compile(lambda);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
260 var keyExpr = context._key.BuildExpression(null, 0);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
261 var keyReader = Expression.Lambda<Func<QueryContext,IDataContext,IDataReader,Expression,object[],TKey>>(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
262 keyExpr,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
263 new []
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
264 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
265 ExpressionBuilder.ContextParam,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
266 ExpressionBuilder.DataContextParam,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
267 ExpressionBuilder.DataReaderParam,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
268 ExpressionBuilder.ExpressionParam,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
269 ExpressionBuilder.ParametersParam,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
270 });
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
271
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
272 return Expression.Call(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
273 null,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
274 ReflectionHelper.Expressor<object>.MethodExpressor(_ => GetGrouping(null, null, null, null, null, null, null, null)),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
275 new Expression[]
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
276 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
277 ExpressionBuilder.ContextParam,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
278 ExpressionBuilder.DataContextParam,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
279 ExpressionBuilder.DataReaderParam,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
280 Expression.Constant(context.Builder.CurrentSqlParameters),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
281 ExpressionBuilder.ExpressionParam,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
282 ExpressionBuilder.ParametersParam,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
283 Expression.Constant(keyReader.Compile()),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
284 Expression.Constant(itemReader),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
285 });
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
286 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
287
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
288 static IGrouping<TKey,TElement> GetGrouping(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
289 QueryContext context,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
290 IDataContext dataContext,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
291 IDataReader dataReader,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
292 List<ParameterAccessor> parameterAccessor,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
293 Expression expr,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
294 object[] ps,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
295 Func<QueryContext,IDataContext,IDataReader,Expression,object[],TKey> keyReader,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
296 Func<IDataContext,TKey,object[],IQueryable<TElement>> itemReader)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
297 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
298 var key = keyReader(context, dataContext, dataReader, expr, ps);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
299 return new Grouping<TKey,TElement>(key, context, parameterAccessor, itemReader);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
300 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
301 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
302
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
303 Expression BuildGrouping()
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
304 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
305 var gtype = typeof(GroupByHelper<,,>).MakeGenericType(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
306 _key.Lambda.Body.Type,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
307 _element.Lambda.Body.Type,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
308 _key.Lambda.Parameters[0].Type);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
309
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
310 var isBlockDisable = Builder.IsBlockDisable;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
311
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
312 Builder.IsBlockDisable = true;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
313
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
314 var helper = (IGroupByHelper)Activator.CreateInstance(gtype);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
315 var expr = helper.GetGrouping(this);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
316
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
317 Builder.IsBlockDisable = isBlockDisable;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
318
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
319 return expr;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
320 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
321
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
322 public override Expression BuildExpression(Expression expression, int level)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
323 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
324 if (expression == null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
325 return BuildGrouping();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
326
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
327 if (level != 0)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
328 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
329 var levelExpression = expression.GetLevelExpression(level);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
330
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
331 if (levelExpression.NodeType == ExpressionType.MemberAccess)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
332 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
333 var ma = (MemberExpression)levelExpression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
334
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
335 if (ma.Member.Name == "Key" && ma.Member.DeclaringType == _groupingType)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
336 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
337 return levelExpression == expression ?
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
338 _key.BuildExpression(null, 0) :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
339 _key.BuildExpression(expression, level + 1);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
340 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
341 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
342 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
343
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
344 throw new InvalidOperationException();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
345 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
346
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
347 ISqlExpression ConvertEnumerable(MethodCallExpression call)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
348 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
349 if (AggregationBuilder.MethodNames.Contains(call.Method.Name))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
350 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
351 if (call.Arguments[0].NodeType == ExpressionType.Call)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
352 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
353 var arg = (MethodCallExpression)call.Arguments[0];
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
354
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
355 if (arg.Method.Name == "Select")
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
356 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
357 if (arg.Arguments[0].NodeType != ExpressionType.Call)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
358 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
359 var l = (LambdaExpression)arg.Arguments[1].Unwrap();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
360 var largs = l.Type.GetGenericArguments();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
361
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
362 if (largs.Length == 2)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
363 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
364 var p = _element.Parent;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
365 var ctx = new ExpressionContext(Parent, _element, l);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
366 var sql = Builder.ConvertToSql(ctx, l.Body, true);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
367
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
368 Builder.ReplaceParent(ctx, p);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
369
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
370 return new SqlFunction(call.Type, call.Method.Name, sql);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
371 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
372 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
373 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
374 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
375 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
376
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
377 if (call.Arguments[0].NodeType == ExpressionType.Call)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
378 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
379 var ctx = Builder.GetSubQuery(this, call);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
380
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
381 if (Builder.SqlProvider.IsSubQueryColumnSupported)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
382 return ctx.SqlQuery;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
383
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
384 var join = ctx.SqlQuery.CrossApply();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
385
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
386 SqlQuery.From.Tables[0].Joins.Add(join.JoinedTable);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
387
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
388 return ctx.SqlQuery.Select.Columns[0];
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
389 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
390
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
391 var args = new ISqlExpression[call.Arguments.Count - 1];
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
392
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
393 if (CountBuilder.MethodNames.Contains(call.Method.Name))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
394 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
395 if (args.Length > 0)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
396 throw new InvalidOperationException();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
397
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
398 return SqlFunction.CreateCount(call.Type, SqlQuery);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
399 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
400
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
401 if (call.Arguments.Count > 1)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
402 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
403 for (var i = 1; i < call.Arguments.Count; i++)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
404 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
405 var ex = call.Arguments[i].Unwrap();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
406
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
407 if (ex is LambdaExpression)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
408 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
409 var l = (LambdaExpression)ex;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
410 var p = _element.Parent;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
411 var ctx = new ExpressionContext(Parent, _element, l);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
412
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
413 args[i - 1] = Builder.ConvertToSql(ctx, l.Body, true);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
414
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
415 Builder.ReplaceParent(ctx, p);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
416 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
417 else
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
418 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
419 throw new InvalidOperationException();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
420 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
421 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
422 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
423 else
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
424 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
425 args = _element.ConvertToSql(null, 0, ConvertFlags.Field).Select(_ => _.Sql).ToArray();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
426 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
427
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
428 return new SqlFunction(call.Type, call.Method.Name, args);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
429 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
430
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
431 PropertyInfo _keyProperty;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
432
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
433 public override SqlInfo[] ConvertToSql(Expression expression, int level, ConvertFlags flags)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
434 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
435 if (expression == null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
436 return _key.ConvertToSql(null, 0, flags);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
437
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
438 if (level > 0)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
439 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
440 switch (expression.NodeType)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
441 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
442 case ExpressionType.Call :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
443 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
444 var e = (MethodCallExpression)expression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
445
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
446 if (e.Method.DeclaringType == typeof(Enumerable))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
447 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
448 return new[] { new SqlInfo { Sql = ConvertEnumerable(e) } };
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
449 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
450
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
451 break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
452 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
453
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
454 case ExpressionType.MemberAccess :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
455 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
456 var levelExpression = expression.GetLevelExpression(level);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
457
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
458 if (levelExpression.NodeType == ExpressionType.MemberAccess)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
459 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
460 var e = (MemberExpression)levelExpression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
461
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
462 if (e.Member.Name == "Key")
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
463 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
464 if (_keyProperty == null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
465 _keyProperty = _groupingType.GetProperty("Key");
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
466
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
467 if (e.Member == _keyProperty)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
468 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
469 if (levelExpression == expression)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
470 return _key.ConvertToSql(null, 0, flags);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
471
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
472 return _key.ConvertToSql(expression, level + 1, flags);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
473 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
474 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
475
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
476 return Sequence.ConvertToSql(expression, level, flags);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
477 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
478
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
479 break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
480 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
481 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
482 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
483
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
484 throw new InvalidOperationException();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
485 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
486
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
487 readonly Dictionary<Tuple<Expression,int,ConvertFlags>,SqlInfo[]> _expressionIndex = new Dictionary<Tuple<Expression,int,ConvertFlags>,SqlInfo[]>();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
488
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
489 public override SqlInfo[] ConvertToIndex(Expression expression, int level, ConvertFlags flags)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
490 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
491 var key = Tuple.Create(expression, level, flags);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
492
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
493 SqlInfo[] info;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
494
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
495 if (!_expressionIndex.TryGetValue(key, out info))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
496 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
497 info = ConvertToSql(expression, level, flags);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
498
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
499 foreach (var item in info)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
500 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
501 item.Query = SqlQuery;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
502 item.Index = SqlQuery.Select.Add(item.Sql);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
503 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
504 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
505
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
506 return info;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
507 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
508
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
509 public override IsExpressionResult IsExpression(Expression expression, int level, RequestFor requestFlag)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
510 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
511 if (level != 0)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
512 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
513 var levelExpression = expression.GetLevelExpression(level);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
514
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
515 if (levelExpression.NodeType == ExpressionType.MemberAccess)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
516 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
517 var ma = (MemberExpression)levelExpression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
518
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
519 if (ma.Member.Name == "Key" && ma.Member.DeclaringType == _groupingType)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
520 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
521 return levelExpression == expression ?
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
522 _key.IsExpression(null, 0, requestFlag) :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
523 _key.IsExpression(expression, level + 1, requestFlag);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
524 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
525 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
526 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
527
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
528 return IsExpressionResult.False;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
529 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
530
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
531 public override int ConvertToParentIndex(int index, IBuildContext context)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
532 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
533 var expr = SqlQuery.Select.Columns[index].Expression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
534
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
535 if (!SqlQuery.GroupBy.Items.Exists(_ => _ == expr || (expr is SqlQuery.Column && _ == ((SqlQuery.Column)expr).Expression)))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
536 SqlQuery.GroupBy.Items.Add(expr);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
537
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
538 return base.ConvertToParentIndex(index, this);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
539 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
540
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
541 interface IContextHelper
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
542 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
543 Expression GetContext(Expression sequence, ParameterExpression param, Expression expr1, Expression expr2);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
544 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
545
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
546 class ContextHelper<T> : IContextHelper
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
547 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
548 public Expression GetContext(Expression sequence, ParameterExpression param, Expression expr1, Expression expr2)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
549 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
550 // ReSharper disable AssignNullToNotNullAttribute
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
551 //ReflectionHelper.Expressor<object>.MethodExpressor(_ => Queryable.Where(null, (Expression<Func<T,bool>>)null)),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
552 var mi = ReflectionHelper.Expressor<object>.MethodExpressor(_ => Enumerable.Where(null, (Func<T,bool>)null));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
553 // ReSharper restore AssignNullToNotNullAttribute
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
554 var arg2 = Expression.Lambda<Func<T,bool>>(Expression.Equal(expr1, expr2), new[] { param });
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
555
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
556 return Expression.Call(null, mi, sequence, arg2);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
557 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
558 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
559
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
560 public override IBuildContext GetContext(Expression expression, int level, BuildInfo buildInfo)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
561 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
562 if (expression == null && buildInfo != null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
563 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
564 if (buildInfo.Parent is SelectManyBuilder.SelectManyContext)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
565 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
566 var sm = (SelectManyBuilder.SelectManyContext)buildInfo.Parent;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
567 var ctype = typeof(ContextHelper<>).MakeGenericType(_key.Lambda.Parameters[0].Type);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
568 var helper = (IContextHelper)Activator.CreateInstance(ctype);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
569 var expr = helper.GetContext(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
570 Sequence.Expression,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
571 _key.Lambda.Parameters[0],
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
572 Expression.PropertyOrField(sm.Lambda.Parameters[0], "Key"),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
573 _key.Lambda.Body);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
574
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
575 return Builder.BuildSequence(new BuildInfo(buildInfo, expr));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
576 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
577
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
578 //if (buildInfo.Parent == this)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
579 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
580 var ctype = typeof(ContextHelper<>).MakeGenericType(_key.Lambda.Parameters[0].Type);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
581 var helper = (IContextHelper)Activator.CreateInstance(ctype);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
582 var expr = helper.GetContext(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
583 _sequenceExpr,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
584 _key.Lambda.Parameters[0],
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
585 Expression.PropertyOrField(buildInfo.Expression, "Key"),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
586 _key.Lambda.Body);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
587
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
588 var ctx = Builder.BuildSequence(new BuildInfo(buildInfo, expr));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
589
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
590 ctx.SqlQuery.Properties.Add(Tuple.Create("from_group_by", SqlQuery));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
591
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
592 return ctx;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
593 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
594
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
595 //return this;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
596 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
597
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
598 if (level != 0)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
599 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
600 var levelExpression = expression.GetLevelExpression(level);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
601
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
602 if (levelExpression.NodeType == ExpressionType.MemberAccess)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
603 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
604 var ma = (MemberExpression)levelExpression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
605
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
606 if (ma.Member.Name == "Key" && ma.Member.DeclaringType == _groupingType)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
607 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
608 return levelExpression == expression ?
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
609 _key.GetContext(null, 0, buildInfo) :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
610 _key.GetContext(expression, level + 1, buildInfo);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
611 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
612 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
613 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
614
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
615 throw new InvalidOperationException();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
616 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
617 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
618
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
619 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
620 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
621 }