annotate Source/Data/Linq/Builder/SelectContext.cs @ 3:1ef98bd70424

!bug 100 +3h Исправление проблемы BLToolkit + mono 3.4
author cin
date Fri, 22 Aug 2014 17:34:46 +0400
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.Generic;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
3 using System.Linq;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
4 using System.Linq.Expressions;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
5 using System.Reflection;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
6
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
7 namespace BLToolkit.Data.Linq.Builder
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
8 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
9 using BLToolkit.Linq;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
10 using Data.Sql;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
11 using Reflection;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
12
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
13 // This class implements double functionality (scalar and member type selects)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
14 // and could be implemented as two different classes.
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
15 // But the class means to have a lot of inheritors, and functionality of the inheritors
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
16 // will be doubled as well. So lets double it once here.
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
17 //
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
18 public class SelectContext : IBuildContext
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
19 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
20 #region Init
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
21
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
22 #if DEBUG
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
23 [CLSCompliant(false)]
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
24 public string _sqlQueryText { get { return SqlQuery == null ? "" : SqlQuery.SqlText; } }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
25
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
26 public MethodCallExpression MethodCall;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
27 #endif
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
28
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
29 public IBuildContext[] Sequence { get; set; }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
30 public LambdaExpression Lambda { get; set; }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
31 public Expression Body { get; set; }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
32 public ExpressionBuilder Builder { get; private set; }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
33 public SqlQuery SqlQuery { get; set; }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
34 public IBuildContext Parent { get; set; }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
35 public bool IsScalar { get; private set; }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
36
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
37 Expression IBuildContext.Expression { get { return Lambda; } }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
38
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
39 public readonly Dictionary<MemberInfo,Expression> Members = new Dictionary<MemberInfo,Expression>(new MemberInfoComparer());
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
40
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
41 public SelectContext(IBuildContext parent, LambdaExpression lambda, params IBuildContext[] sequences)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
42 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
43 Parent = parent;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
44 Sequence = sequences;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
45 Builder = sequences[0].Builder;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
46 Lambda = lambda;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
47 Body = lambda.Body;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
48 SqlQuery = sequences[0].SqlQuery;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
49
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
50 foreach (var context in Sequence)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
51 context.Parent = this;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
52
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
53 IsScalar = !Builder.ProcessProjection(Members, Body);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
54
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
55 Builder.Contexts.Add(this);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
56 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
57
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
58 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
59
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
60 #region BuildQuery
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
61
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
62 public virtual void BuildQuery<T>(Query<T> query, ParameterExpression queryParameter)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
63 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
64 var expr = BuildExpression(null, 0);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
65 var mapper = Builder.BuildMapper<T>(expr);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
66
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
67 query.SetQuery(mapper.Compile());
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
68 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
69
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
70 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
71
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
72 #region BuildExpression
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
73
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
74 public virtual Expression BuildExpression(Expression expression, int level)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
75 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
76 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
77 var key = Tuple.Create(expression, level, ConvertFlags.Field);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
78
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
79 SqlInfo[] info;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
80
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
81 if (_expressionIndex.TryGetValue(key, out info))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
82 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
83 var idx = Parent == null ? info[0].Index : Parent.ConvertToParentIndex(info[0].Index, this);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
84 return Builder.BuildSql((expression ?? Body).Type, idx);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
85 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
86 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
87
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
88 if (expression == null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
89 return Builder.BuildExpression(this, Body);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
90
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
91 var levelExpression = expression.GetLevelExpression(level);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
92
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
93 if (IsScalar)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
94 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
95 if (Body.NodeType != ExpressionType.Parameter && level == 0)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
96 if (levelExpression == expression)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
97 if (IsSubQuery() && IsExpression(null, 0, RequestFor.Expression).Result)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
98 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
99 var info = ConvertToIndex(expression, level, ConvertFlags.Field).Single();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
100 var idx = Parent == null ? info.Index : Parent.ConvertToParentIndex(info.Index, this);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
101
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
102 return Builder.BuildSql(expression.Type, idx);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
103 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
104
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
105 return ProcessScalar(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
106 expression,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
107 level,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
108 (ctx, ex, l) => ctx.BuildExpression(ex, l),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
109 () => GetSequence(expression, level).BuildExpression(null, 0));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
110 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
111 else
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
112 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
113 if (level == 0)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
114 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
115 var sequence = GetSequence(expression, level);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
116
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
117 return levelExpression == expression ?
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
118 sequence.BuildExpression(null, 0) :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
119 sequence.BuildExpression(expression, level + 1);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
120 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
121
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
122 switch (levelExpression.NodeType)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
123 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
124 case ExpressionType.MemberAccess :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
125 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
126 var memberExpression = GetMemberExpression(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
127 ((MemberExpression)levelExpression).Member,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
128 levelExpression == expression,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
129 levelExpression.Type);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
130
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
131 if (levelExpression == expression)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
132 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
133 if (IsSubQuery())
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
134 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
135 switch (memberExpression.NodeType)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
136 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
137 case ExpressionType.New :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
138 case ExpressionType.MemberInit :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
139 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
140 return memberExpression.Convert(e =>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
141 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
142 if (e != memberExpression)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
143 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
144 switch (e.NodeType)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
145 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
146 case ExpressionType.MemberAccess :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
147 var sequence = GetSequence(memberExpression, 0);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
148
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
149 if (sequence != null &&
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
150 !sequence.IsExpression(e, 0, RequestFor.Object).Result &&
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
151 !sequence.IsExpression(e, 0, RequestFor.Field). Result)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
152 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
153 var info = ConvertToIndex(e, 0, ConvertFlags.Field).Single();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
154 var idx = Parent == null ? info.Index : Parent.ConvertToParentIndex(info.Index, this);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
155
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
156 return Builder.BuildSql(e.Type, idx);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
157 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
158
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
159 return Builder.BuildExpression(this, e);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
160 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
161 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
162
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
163 return e;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
164 });
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
165 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
166 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
167
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
168 var me = memberExpression.NodeType == ExpressionType.Parameter ? null : memberExpression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
169
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
170 if (!IsExpression(me, 0, RequestFor.Object).Result &&
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
171 !IsExpression(me, 0, RequestFor.Field). Result)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
172 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
173 var info = ConvertToIndex(expression, level, ConvertFlags.Field).Single();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
174 var idx = Parent == null ? info.Index : Parent.ConvertToParentIndex(info.Index, this);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
175
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
176 return Builder.BuildSql(expression.Type, idx);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
177 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
178 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
179
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
180 return Builder.BuildExpression(this, memberExpression);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
181 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
182
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
183 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
184 var sequence = GetSequence(expression, level);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
185
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
186 switch (memberExpression.NodeType)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
187 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
188 case ExpressionType.Parameter :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
189 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
190 var parameter = Lambda.Parameters[Sequence.Length == 0 ? 0 : Array.IndexOf(Sequence, sequence)];
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
191
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
192 if (memberExpression == parameter)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
193 return sequence.BuildExpression(expression, level + 1);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
194
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
195 break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
196
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
197 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
198
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
199 case ExpressionType.New :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
200 case ExpressionType.MemberInit :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
201 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
202 var mmExpresion = GetMemberExpression(memberExpression, expression, level + 1);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
203 return Builder.BuildExpression(this, mmExpresion);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
204 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
205 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
206
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
207 var expr = expression.Convert(ex => ex == levelExpression ? memberExpression : ex);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
208
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
209 return sequence.BuildExpression(expr, 1);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
210 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
211 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
212
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
213 case ExpressionType.Parameter :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
214 break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
215 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
216 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
217
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
218 throw new InvalidOperationException();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
219 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
220
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
221 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
222
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
223 #region ConvertToSql
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
224
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
225 readonly Dictionary<MemberInfo,SqlInfo[]> _sql = new Dictionary<MemberInfo,SqlInfo[]>(new MemberInfoComparer());
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
226
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
227 public virtual SqlInfo[] ConvertToSql(Expression expression, int level, ConvertFlags flags)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
228 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
229 if (expression != null && level > 0 && expression.NodeType == ExpressionType.Call)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
230 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
231 var e = (MethodCallExpression)expression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
232
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
233 if (e.Method.DeclaringType == typeof(Enumerable))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
234 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
235 return new[] { new SqlInfo { Sql = Builder.SubQueryToSql(this, e) } };
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
236 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
237 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
238
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
239 if (IsScalar)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
240 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
241 if (expression == null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
242 return Builder.ConvertExpressions(this, Body, flags);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
243
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
244 switch (flags)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
245 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
246 case ConvertFlags.Field :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
247 case ConvertFlags.Key :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
248 case ConvertFlags.All :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
249 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
250 if (Body.NodeType != ExpressionType.Parameter && level == 0)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
251 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
252 var levelExpression = expression.GetLevelExpression(level);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
253
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
254 if (levelExpression != expression)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
255 if (flags != ConvertFlags.Field && IsExpression(expression, level, RequestFor.Field).Result)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
256 flags = ConvertFlags.Field;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
257 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
258
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
259 return ProcessScalar(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
260 expression,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
261 level,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
262 (ctx, ex, l) => ctx.ConvertToSql(ex, l, flags),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
263 () => new[] { new SqlInfo { Sql = Builder.ConvertToSql(this, expression, false) } });
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
264 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
265 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
266 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
267 else
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
268 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
269 if (expression == null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
270 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
271 if (flags != ConvertFlags.Field)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
272 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
273 var q =
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
274 from m in Members
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
275 where !(m.Key is MethodInfo)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
276 select ConvertMember(m.Key, m.Value, flags) into mm
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
277 from m in mm
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
278 select m;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
279
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
280 return q.ToArray();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
281 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
282
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
283 throw new InvalidOperationException();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
284 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
285
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
286 switch (flags)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
287 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
288 case ConvertFlags.All :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
289 case ConvertFlags.Key :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
290 case ConvertFlags.Field :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
291 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
292 var levelExpression = expression.GetLevelExpression(level);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
293
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
294 switch (levelExpression.NodeType)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
295 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
296 case ExpressionType.MemberAccess :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
297 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
298 if (level != 0 && levelExpression == expression)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
299 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
300 var member = ((MemberExpression)levelExpression).Member;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
301
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
302 SqlInfo[] sql;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
303
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
304 if (!_sql.TryGetValue(member, out sql))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
305 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
306 var memberExpression = GetMemberExpression(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
307 member, levelExpression == expression, levelExpression.Type);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
308
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
309 sql = ConvertExpressions(memberExpression, flags)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
310 .Select(si => si.Clone(member)).ToArray();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
311
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
312 _sql.Add(member, sql);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
313 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
314
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
315 return sql;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
316 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
317
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
318 return ProcessMemberAccess(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
319 expression, (MemberExpression)levelExpression, level,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
320 (n,ctx,ex,l,mex) =>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
321 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
322 switch (n)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
323 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
324 case 0 :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
325 var buildExpression = GetExpression(expression, levelExpression, mex);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
326 return ConvertExpressions(buildExpression, flags);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
327 default:
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
328 return ctx.ConvertToSql(ex, l, flags);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
329 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
330 });
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
331 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
332
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
333 case ExpressionType.Parameter:
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
334 if (levelExpression != expression)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
335 return GetSequence(expression, level).ConvertToSql(expression, level + 1, flags);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
336
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
337 if (level == 0)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
338 return GetSequence(expression, level).ConvertToSql(null, 0, flags);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
339
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
340 break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
341
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
342 default:
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
343 if (level == 0)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
344 return Builder.ConvertExpressions(this, expression, flags);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
345 break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
346 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
347
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
348 break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
349 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
350 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
351 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
352
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
353 throw new InvalidOperationException();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
354 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
355
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
356 SqlInfo[] ConvertMember(MemberInfo member, Expression expression, ConvertFlags flags)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
357 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
358 return ConvertExpressions(expression, flags)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
359 .Select(si => si.Clone(member))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
360 .ToArray();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
361 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
362
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
363 SqlInfo[] ConvertExpressions(Expression expression, ConvertFlags flags)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
364 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
365 return Builder.ConvertExpressions(this, expression, flags)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
366 .Select(CheckExpression)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
367 .ToArray();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
368 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
369
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
370 SqlInfo CheckExpression(SqlInfo expression)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
371 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
372 if (expression.Sql is SqlQuery.SearchCondition)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
373 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
374 expression.Sql = Builder.Convert(this, new SqlFunction(typeof(bool), "CASE", expression.Sql, new SqlValue(true), new SqlValue(false)));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
375 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
376
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
377 return expression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
378 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
379
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
380 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
381
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
382 #region ConvertToIndex
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
383
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
384 readonly Dictionary<Tuple<Expression,int,ConvertFlags>,SqlInfo[]> _expressionIndex = new Dictionary<Tuple<Expression,int,ConvertFlags>,SqlInfo[]>();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
385
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
386 public virtual SqlInfo[] ConvertToIndex(Expression expression, int level, ConvertFlags flags)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
387 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
388 var key = Tuple.Create(expression, level, flags);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
389
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
390 SqlInfo[] info;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
391
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
392 if (!_expressionIndex.TryGetValue(key, out info))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
393 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
394 info = ConvertToIndexInternal(expression, level, flags);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
395
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
396 var newInfo = info
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
397 .Select(i =>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
398 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
399 if (i.Query == SqlQuery)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
400 return i;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
401
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
402 return new SqlInfo(i.Members)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
403 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
404 Query = SqlQuery,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
405 Index = SqlQuery.Select.Add(i.Query.Select.Columns[i.Index])
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
406 };
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
407 })
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
408 .ToArray();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
409
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
410 _expressionIndex.Add(key, newInfo);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
411
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
412 return newInfo;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
413 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
414
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
415 return info;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
416 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
417
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
418 readonly Dictionary<Tuple<MemberInfo,ConvertFlags>,SqlInfo[]> _memberIndex = new Dictionary<Tuple<MemberInfo,ConvertFlags>,SqlInfo[]>();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
419
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
420 SqlInfo[] ConvertToIndexInternal(Expression expression, int level, ConvertFlags flags)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
421 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
422 if (IsScalar)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
423 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
424 if (Body.NodeType == ExpressionType.Parameter)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
425 for (var i = 0; i < Sequence.Length; i++)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
426 if (Body == Lambda.Parameters[i])
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
427 return Sequence[i].ConvertToIndex(expression, level, flags);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
428
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
429 if (expression == null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
430 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
431 var key = Tuple.Create((MemberInfo)null, flags);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
432
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
433 SqlInfo[] idx;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
434
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
435 if (!_memberIndex.TryGetValue(key, out idx))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
436 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
437 idx = ConvertToSql(null, 0, flags);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
438
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
439 foreach (var info in idx)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
440 SetInfo(info);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
441
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
442 _memberIndex.Add(key, idx);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
443 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
444
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
445 return idx;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
446 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
447
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
448 switch (flags)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
449 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
450 case ConvertFlags.Field :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
451 case ConvertFlags.All :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
452 return ProcessScalar(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
453 expression,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
454 level,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
455 (ctx, ex, l) => ctx.ConvertToIndex(ex, l, flags),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
456 () => GetSequence(expression, level).ConvertToIndex(expression, level + 1, flags));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
457 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
458 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
459 else
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
460 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
461 if (expression == null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
462 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
463 switch (flags)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
464 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
465 case ConvertFlags.Field : throw new InvalidOperationException();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
466 case ConvertFlags.Key :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
467 case ConvertFlags.All :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
468 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
469 var p = Expression.Parameter(Body.Type, "p");
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
470 var q =
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
471 from m in Members.Keys
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
472 where !(m is MethodInfo)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
473 select new
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
474 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
475 Sql = ConvertToIndex(Expression.MakeMemberAccess(p, m), 1, flags),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
476 Member = m
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
477 } into mm
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
478 from m in mm.Sql.Select(s => s.Clone(mm.Member))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
479 select m;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
480
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
481 return q.ToArray();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
482 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
483 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
484 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
485
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
486 switch (flags)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
487 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
488 case ConvertFlags.All :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
489 case ConvertFlags.Key :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
490 case ConvertFlags.Field :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
491 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
492 if (level == 0)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
493 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
494 var idx = Builder.ConvertExpressions(this, expression, flags);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
495
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
496 foreach (var info in idx)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
497 SetInfo(info);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
498
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
499 return idx;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
500 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
501
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
502 var levelExpression = expression.GetLevelExpression(level);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
503
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
504 switch (levelExpression.NodeType)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
505 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
506 case ExpressionType.MemberAccess :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
507 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
508 if (levelExpression == expression)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
509 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
510 var member = Tuple.Create(((MemberExpression)levelExpression).Member, flags);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
511
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
512 SqlInfo[] idx;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
513
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
514 if (!_memberIndex.TryGetValue(member, out idx))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
515 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
516 idx = ConvertToSql(expression, level, flags);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
517
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
518 if (flags == ConvertFlags.Field && idx.Length != 1)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
519 throw new InvalidOperationException();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
520
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
521 foreach (var info in idx)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
522 SetInfo(info);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
523
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
524 _memberIndex.Add(member, idx);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
525 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
526
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
527 return idx;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
528 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
529
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
530 return ProcessMemberAccess(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
531 expression,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
532 (MemberExpression)levelExpression,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
533 level,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
534 (n, ctx, ex, l, _) => n == 0 ?
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
535 GetSequence(expression, level).ConvertToIndex(expression, level + 1, flags) :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
536 ctx.ConvertToIndex(ex, l, flags));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
537 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
538
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
539 case ExpressionType.Parameter:
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
540
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
541 if (levelExpression != expression)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
542 return GetSequence(expression, level).ConvertToIndex(expression, level + 1, flags);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
543 break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
544 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
545
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
546 break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
547 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
548 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
549 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
550
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
551 throw new InvalidOperationException();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
552 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
553
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
554 void SetInfo(SqlInfo info)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
555 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
556 info.Query = SqlQuery;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
557
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
558 if (info.Sql == SqlQuery)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
559 info.Index = SqlQuery.Select.Columns.Count - 1;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
560 else
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
561 info.Index = SqlQuery.Select.Add(info.Sql);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
562 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
563
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
564 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
565
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
566 #region IsExpression
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
567
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
568 public virtual IsExpressionResult IsExpression(Expression expression, int level, RequestFor requestFlag)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
569 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
570 switch (requestFlag)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
571 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
572 case RequestFor.SubQuery : return IsExpressionResult.False;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
573 case RequestFor.Root :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
574 return new IsExpressionResult(Sequence.Length == 1 ?
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
575 expression == Lambda.Parameters[0] :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
576 Lambda.Parameters.Any(p => p == expression));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
577 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
578
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
579 if (IsScalar)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
580 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
581 if (expression == null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
582 return IsExpression(Body, 0, requestFlag);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
583
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
584 switch (requestFlag)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
585 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
586 default : return IsExpressionResult.False;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
587 case RequestFor.Table :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
588 case RequestFor.Association :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
589 case RequestFor.Field :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
590 case RequestFor.Expression :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
591 case RequestFor.Object :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
592 case RequestFor.GroupJoin :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
593 return ProcessScalar(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
594 expression,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
595 level,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
596 (ctx, ex, l) => ctx.IsExpression(ex, l, requestFlag),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
597 () => new IsExpressionResult(requestFlag == RequestFor.Expression));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
598 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
599 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
600 else
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
601 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
602 switch (requestFlag)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
603 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
604 default : return IsExpressionResult.False;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
605 case RequestFor.Table :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
606 case RequestFor.Association :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
607 case RequestFor.Field :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
608 case RequestFor.Expression :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
609 case RequestFor.Object :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
610 case RequestFor.GroupJoin :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
611 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
612 if (expression == null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
613 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
614 if (requestFlag == RequestFor.Expression)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
615 return new IsExpressionResult(Members.Values.Any(member => IsExpression(member, 0, requestFlag).Result));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
616
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
617 return new IsExpressionResult(requestFlag == RequestFor.Object);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
618 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
619
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
620 var levelExpression = expression.GetLevelExpression(level);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
621
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
622 switch (levelExpression.NodeType)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
623 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
624 case ExpressionType.MemberAccess :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
625 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
626 var member = ((MemberExpression)levelExpression).Member;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
627
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
628 Expression memberExpression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
629
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
630 if (!Members.TryGetValue(member, out memberExpression))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
631 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
632 var nm = Members.Keys.FirstOrDefault(m => m.Name == member.Name);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
633
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
634 if (nm != null && member.DeclaringType.IsInterface)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
635 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
636 if (TypeHelper.IsSameOrParent(member.DeclaringType, nm.DeclaringType))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
637 memberExpression = Members[nm];
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
638 else
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
639 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
640 var mdt = TypeHelper.GetDefiningTypes(member.DeclaringType, member);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
641 var ndt = TypeHelper.GetDefiningTypes(Body.Type, nm);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
642
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
643 if (mdt.Intersect(ndt).Any())
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
644 memberExpression = Members[nm];
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
645 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
646 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
647
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
648 if (memberExpression == null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
649 return new IsExpressionResult(requestFlag == RequestFor.Expression);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
650 //throw new InvalidOperationException(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
651 // string.Format("Invalid member '{0}.{1}'", member.DeclaringType, member.Name));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
652 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
653
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
654 if (levelExpression == expression)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
655 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
656 switch (memberExpression.NodeType)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
657 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
658 case ExpressionType.New :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
659 case ExpressionType.MemberInit :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
660 return new IsExpressionResult(requestFlag == RequestFor.Object);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
661 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
662 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
663
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
664 return ProcessMemberAccess(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
665 expression,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
666 (MemberExpression)levelExpression,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
667 level,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
668 (n,ctx,ex,l,_) => n == 0 ?
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
669 new IsExpressionResult(requestFlag == RequestFor.Expression) :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
670 ctx.IsExpression(ex, l, requestFlag));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
671 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
672
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
673 case ExpressionType.Parameter :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
674 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
675 var sequence = GetSequence(expression, level);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
676 var parameter = Lambda.Parameters[Sequence.Length == 0 ? 0 : Array.IndexOf(Sequence, sequence)];
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
677
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
678 if (levelExpression == expression)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
679 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
680 if (levelExpression == parameter)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
681 return sequence.IsExpression(null, 0, requestFlag);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
682 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
683 else if (level == 0)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
684 return sequence.IsExpression(expression, 1, requestFlag);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
685
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
686 break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
687 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
688
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
689 case ExpressionType.New :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
690 case ExpressionType.MemberInit : return new IsExpressionResult(requestFlag == RequestFor.Object);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
691 default : return new IsExpressionResult(requestFlag == RequestFor.Expression);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
692 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
693
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
694 break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
695 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
696 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
697 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
698
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
699 throw new InvalidOperationException();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
700 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
701
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
702 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
703
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
704 #region GetContext
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
705
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
706 public virtual IBuildContext GetContext(Expression expression, int level, BuildInfo buildInfo)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
707 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
708 if (expression == null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
709 return this;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
710
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
711 if (IsScalar)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
712 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
713 return ProcessScalar(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
714 expression,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
715 level,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
716 (ctx, ex, l) => ctx.GetContext(ex, l, buildInfo),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
717 () => { throw new InvalidOperationException(); });
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
718 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
719 else
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
720 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
721 var levelExpression = expression.GetLevelExpression(level);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
722
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
723 switch (levelExpression.NodeType)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
724 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
725 case ExpressionType.MemberAccess :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
726 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
727 if (levelExpression == expression && Sequence.Length == 1 && !(Sequence[0] is GroupByBuilder.GroupByContext))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
728 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
729 var memberExpression = GetMemberExpression(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
730 ((MemberExpression)levelExpression).Member,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
731 levelExpression == expression,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
732 levelExpression.Type);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
733
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
734 //var sequence = GetSequence(memberExpression, 0);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
735 //return sequence.GetContext(memberExpression, 1, new BuildInfo(buildInfo, memberExpression));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
736
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
737 var ctx = GetContext(memberExpression, 0, new BuildInfo(this, memberExpression, buildInfo.SqlQuery));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
738
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
739 if (ctx != null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
740 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
741 return ctx;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
742 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
743 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
744
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
745 var context = ProcessMemberAccess(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
746 expression,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
747 (MemberExpression)levelExpression,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
748 level,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
749 (n,ctx,ex,l,_) => n == 0 ?
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
750 null :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
751 ctx.GetContext(ex, l, buildInfo));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
752
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
753 if (context == null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
754 throw new InvalidOperationException();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
755
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
756 return context;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
757 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
758
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
759 case ExpressionType.Parameter :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
760 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
761 var sequence = GetSequence(expression, level);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
762 var parameter = Lambda.Parameters[Sequence.Length == 0 ? 0 : Array.IndexOf(Sequence, sequence)];
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
763
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
764 if (levelExpression == expression)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
765 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
766 if (levelExpression == parameter)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
767 return sequence.GetContext(null, 0, buildInfo);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
768 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
769 else if (level == 0)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
770 return sequence.GetContext(expression, 1, buildInfo);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
771
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
772 break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
773 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
774 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
775
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
776 if (level == 0)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
777 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
778 var sequence = GetSequence(expression, level);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
779 return sequence.GetContext(expression, level + 1, buildInfo);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
780 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
781 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
782
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
783 throw new InvalidOperationException();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
784 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
785
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
786 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
787
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
788 #region ConvertToParentIndex
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
789
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
790 public virtual int ConvertToParentIndex(int index, IBuildContext context)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
791 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
792 if (context.SqlQuery != SqlQuery)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
793 index = SqlQuery.Select.Add(context.SqlQuery.Select.Columns[index]);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
794
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
795 return Parent == null ? index : Parent.ConvertToParentIndex(index, this);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
796 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
797
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
798 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
799
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
800 #region SetAlias
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
801
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
802 public virtual void SetAlias(string alias)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
803 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
804 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
805
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
806 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
807
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
808 #region GetSubQuery
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
809
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
810 public ISqlExpression GetSubQuery(IBuildContext context)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
811 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
812 return null;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
813 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
814
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
815 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
816
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
817 #region Helpers
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
818
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
819 T ProcessScalar<T>(Expression expression, int level, Func<IBuildContext,Expression,int,T> action, Func<T> defaultAction)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
820 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
821 if (level == 0)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
822 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
823 if (Body.NodeType == ExpressionType.Parameter)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
824 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
825 var sequence = GetSequence(Body, 0);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
826
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
827 return expression == Body ?
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
828 action(sequence, null, 0) :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
829 action(sequence, expression, 1);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
830 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
831
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
832 var levelExpression = expression.GetLevelExpression(level);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
833
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
834 if (levelExpression != expression)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
835 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
836 var ctx = GetSequence(expression, level);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
837 return ctx == null ? defaultAction() : action(ctx, expression, Sequence.Contains(ctx) ? level + 1 : 0);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
838 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
839
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
840 if (expression.NodeType == ExpressionType.Parameter)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
841 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
842 var sequence = GetSequence(expression, level);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
843 var parameter = Lambda.Parameters[Sequence.Length == 0 ? 0 : Array.IndexOf(Sequence, sequence)];
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
844
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
845 if (levelExpression == parameter)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
846 return action(sequence, null, 0);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
847 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
848
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
849 switch (Body.NodeType)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
850 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
851 case ExpressionType.MemberAccess : return action(GetSequence(expression, level), null, 0);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
852 default : return defaultAction();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
853 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
854 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
855 else
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
856 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
857 var root = Body.GetRootObject();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
858
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
859 if (root.NodeType == ExpressionType.Parameter)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
860 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
861 var levelExpression = expression.GetLevelExpression(level - 1);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
862 var newExpression = GetExpression(expression, levelExpression, Body);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
863
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
864 return action(this, newExpression, 0);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
865 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
866 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
867
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
868 throw new InvalidOperationException();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
869 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
870
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
871 T ProcessMemberAccess<T>(Expression expression, MemberExpression levelExpression, int level,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
872 Func<int,IBuildContext,Expression,int,Expression,T> action)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
873 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
874 var memberExpression = Members[levelExpression.Member];
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
875 var newExpression = GetExpression(expression, levelExpression, memberExpression);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
876 var sequence = GetSequence (expression, level);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
877 var nextLevel = 1;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
878
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
879 if (sequence != null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
880 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
881 var idx = Sequence.Length == 0 ? 0 : Array.IndexOf(Sequence, sequence);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
882
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
883 if (idx >= 0)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
884 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
885 var parameter = Lambda.Parameters[idx];
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
886
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
887 if (levelExpression == expression)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
888 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
889 if (memberExpression == parameter)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
890 return action(1, sequence, null, 0, memberExpression);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
891
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
892 // if (!(sequence is GroupByBuilder.GroupByContext) && memberExpression.GetRootObject() == parameter)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
893 // return action(3, this, newExpression, 0, memberExpression);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
894 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
895 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
896 else
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
897 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
898 nextLevel = 0;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
899 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
900 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
901
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
902 switch (memberExpression.NodeType)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
903 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
904 case ExpressionType.MemberAccess :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
905 case ExpressionType.Parameter :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
906 if (sequence != null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
907 return action(2, sequence, newExpression, nextLevel, memberExpression);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
908 throw new InvalidOperationException();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
909
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
910 case ExpressionType.New :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
911 case ExpressionType.MemberInit :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
912 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
913 var mmExpresion = GetMemberExpression(memberExpression, expression, level + 1);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
914 return action(3, this, mmExpresion, 0, memberExpression);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
915 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
916 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
917
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
918 return action(0, this, null, 0, memberExpression);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
919 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
920
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
921 protected bool IsSubQuery()
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
922 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
923 for (var p = Parent; p != null; p = p.Parent)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
924 if (p.IsExpression(null, 0, RequestFor.SubQuery).Result)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
925 return true;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
926 return false;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
927 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
928
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
929 IBuildContext GetSequence(Expression expression, int level)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
930 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
931 if (Sequence.Length == 1 && Sequence[0].Parent == null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
932 return Sequence[0];
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
933
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
934 Expression root = null;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
935
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
936 if (IsScalar)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
937 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
938 root = expression.GetRootObject();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
939 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
940 else
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
941 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
942 var levelExpression = expression.GetLevelExpression(level);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
943
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
944 switch (levelExpression.NodeType)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
945 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
946 case ExpressionType.MemberAccess :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
947 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
948 var memberExpression = Members[((MemberExpression)levelExpression).Member];
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
949
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
950 root = memberExpression.GetRootObject();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
951
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
952 if (root.NodeType != ExpressionType.Parameter)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
953 return null;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
954
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
955 break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
956 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
957
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
958 case ExpressionType.Parameter :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
959 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
960 root = expression.GetRootObject();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
961 break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
962 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
963 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
964 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
965
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
966 if (root != null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
967 for (var i = 0; i < Lambda.Parameters.Count; i++)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
968 if (root == Lambda.Parameters[i])
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
969 return Sequence[i];
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
970
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
971 foreach (var context in Sequence)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
972 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
973 if (context.Parent != null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
974 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
975 var ctx = Builder.GetContext(context, root);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
976 if (ctx != null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
977 return ctx;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
978 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
979 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
980
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
981 return null;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
982 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
983
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
984 static Expression GetExpression(Expression expression, Expression levelExpression, Expression memberExpression)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
985 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
986 return levelExpression != expression ?
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
987 expression.Convert(ex => ex == levelExpression ? memberExpression : ex) :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
988 memberExpression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
989 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
990
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
991 static Expression GetMemberExpression(Expression newExpression, Expression expression, int level)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
992 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
993 var levelExpresion = expression.GetLevelExpression(level);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
994
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
995 switch (newExpression.NodeType)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
996 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
997 case ExpressionType.New :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
998 case ExpressionType.MemberInit : break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
999 default :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1000 var le = expression.GetLevelExpression(level - 1);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1001 return GetExpression(expression, le, newExpression);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1002 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1003
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1004 if (levelExpresion.NodeType != ExpressionType.MemberAccess)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1005 throw new LinqException("Invalid expression {0}", levelExpresion);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1006
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1007 var me = (MemberExpression)levelExpresion;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1008
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1009 switch (newExpression.NodeType)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1010 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1011 case ExpressionType.New:
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1012 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1013 var expr = (NewExpression)newExpression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1014
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1015 // ReSharper disable ConditionIsAlwaysTrueOrFalse
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1016 // ReSharper disable HeuristicUnreachableCode
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1017 if (expr.Members == null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1018 throw new LinqException("Invalid expression {0}", expression);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1019 // ReSharper restore HeuristicUnreachableCode
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1020 // ReSharper restore ConditionIsAlwaysTrueOrFalse
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1021
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1022 for (var i = 0; i < expr.Members.Count; i++)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1023 if (me.Member == expr.Members[i])
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1024 return levelExpresion == expression ?
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1025 expr.Arguments[i].Unwrap() :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1026 GetMemberExpression(expr.Arguments[i].Unwrap(), expression, level + 1);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1027
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1028 throw new LinqException("Invalid expression {0}", expression);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1029 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1030
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1031 case ExpressionType.MemberInit:
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1032 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1033 var expr = (MemberInitExpression)newExpression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1034
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1035 foreach (var binding in expr.Bindings.Cast<MemberAssignment>())
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1036 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1037 if (me.Member == binding.Member)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1038 return levelExpresion == expression ?
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1039 binding.Expression.Unwrap() :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1040 GetMemberExpression(binding.Expression.Unwrap(), expression, level + 1);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1041 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1042
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1043 throw new LinqException("Invalid expression {0}", expression);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1044 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1045 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1046
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1047 return expression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1048 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1049
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1050 Expression GetMemberExpression(MemberInfo member, bool add, Type type)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1051 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1052 Expression memberExpression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1053
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1054 if (!Members.TryGetValue(member, out memberExpression))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1055 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1056 foreach (var m in Members)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1057 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1058 if (m.Key.Name == member.Name)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1059 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1060 if (TypeHelper.Equals(m.Key, member, IsScalar ? null : Body.Type))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1061 return m.Value;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1062 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1063 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1064
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1065 if (add && TypeHelper.IsSameOrParent(member.DeclaringType, Body.Type))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1066 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1067 memberExpression = Expression.Constant(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1068 TypeHelper.GetDefaultValue(type), type);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1069
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1070 Members.Add(member, memberExpression);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1071 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1072 else
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1073 throw new InvalidOperationException();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1074 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1075
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1076 return memberExpression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1077 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1078
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1079 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1080 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1081 }