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

Исправлена странная ошибка при использовании OfType<...>().Where(...)
author cin
date Mon, 05 Dec 2016 05:50:52 +0300
parents f990fcb411a9
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1 using System;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2 using System.Collections.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
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
6 namespace BLToolkit.Data.Linq.Builder
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
7 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
8 using BLToolkit.Linq;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
9 using Data.Sql;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
10
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
11 class SubQueryContext : PassThroughContext
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
12 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
13 public readonly IBuildContext SubQuery;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
14
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
15 public SubQueryContext(IBuildContext subQuery, SqlQuery sqlQuery, bool addToSql)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
16 : base(subQuery)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
17 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
18 if (sqlQuery == subQuery.SqlQuery)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
19 throw new ArgumentException("Wrong subQuery argument.", "subQuery");
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
20
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
21 SubQuery = subQuery;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
22 SubQuery.Parent = this;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
23
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
24 SqlQuery = sqlQuery;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
25
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
26 if (addToSql)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
27 sqlQuery.From.Table(SubQuery.SqlQuery);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
28 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
29
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
30 public SubQueryContext(IBuildContext subQuery, bool addToSql)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
31 : this(subQuery, new SqlQuery { ParentSql = subQuery.SqlQuery.ParentSql }, addToSql)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
32 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
33 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
34
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
35 public SubQueryContext(IBuildContext subQuery)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
36 : this(subQuery, true)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
37 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
38 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
39
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
40 public override SqlQuery SqlQuery { get; set; }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
41 public override IBuildContext Parent { get; set; }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
42
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
43 public override void BuildQuery<T>(Query<T> query, ParameterExpression queryParameter)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
44 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
45 if (Expression.NodeType == ExpressionType.Lambda)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
46 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
47 var le = (LambdaExpression)Expression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
48
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
49 if (le.Parameters.Count == 1 && null != Expression.Find(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
50 e => e.NodeType == ExpressionType.Call && ((MethodCallExpression)e).IsQueryable()))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
51 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
52 if (le.Body.NodeType == ExpressionType.New)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
53 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
54 var ne = (NewExpression)le.Body;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
55 var p = Expression.Parameter(ne.Type, "p");
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
56
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
57 var seq = new SelectContext(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
58 Parent,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
59 Expression.Lambda(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
60 Expression.New(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
61 ne.Constructor,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
62 ne.Members.Select(m => Expression.MakeMemberAccess(p, m)).ToArray(),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
63 ne.Members),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
64 p),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
65 this);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
66
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
67 seq.BuildQuery(query, queryParameter);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
68
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
69 return;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
70 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
71
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
72 if (le.Body.NodeType == ExpressionType.MemberInit)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
73 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
74 var mi = (MemberInitExpression)le.Body;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
75
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
76 if (mi.NewExpression.Arguments.Count == 0 && mi.Bindings.All(b => b is MemberAssignment))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
77 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
78 var p = Expression.Parameter(mi.Type, "p");
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
79
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
80 var seq = new SelectContext(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
81 Parent,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
82 Expression.Lambda(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
83 Expression.MemberInit(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
84 mi.NewExpression,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
85 mi.Bindings
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
86 .OfType<MemberAssignment>()
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
87 .Select(ma => Expression.Bind(ma.Member, Expression.MakeMemberAccess(p, ma.Member)))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
88 .ToArray()),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
89 p),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
90 this);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
91
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
92 seq.BuildQuery(query, queryParameter);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
93
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
94 return;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
95 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
96 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
97 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
98 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
99
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
100 base.BuildQuery(query, queryParameter);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
101 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
102
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
103 public override SqlInfo[] ConvertToSql(Expression expression, int level, ConvertFlags flags)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
104 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
105 return SubQuery
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
106 .ConvertToIndex(expression, level, flags)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
107 .Select(idx => new SqlInfo(idx.Members) { Sql = SubQuery.SqlQuery.Select.Columns[idx.Index] })
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
108 .ToArray();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
109 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
110
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
111 // JoinContext has similar logic. Consider to review it.
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
112 //
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
113 public override SqlInfo[] ConvertToIndex(Expression expression, int level, ConvertFlags flags)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
114 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
115 return ConvertToSql(expression, level, flags)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
116 .Select(idx =>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
117 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
118 idx.Query = SqlQuery;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
119 idx.Index = GetIndex((SqlQuery.Column)idx.Sql);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
120
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
121 return idx;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
122 })
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
123 .ToArray();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
124 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
125
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
126 public override IsExpressionResult IsExpression(Expression expression, int level, RequestFor testFlag)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
127 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
128 switch (testFlag)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
129 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
130 case RequestFor.SubQuery : return IsExpressionResult.True;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
131 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
132
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
133 return base.IsExpression(expression, level, testFlag);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
134 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
135
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
136 internal protected readonly Dictionary<ISqlExpression,int> ColumnIndexes = new Dictionary<ISqlExpression,int>();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
137
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
138 protected virtual int GetIndex(SqlQuery.Column column)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
139 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
140 int idx;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
141
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
142 if (!ColumnIndexes.TryGetValue(column, out idx))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
143 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
144 idx = SqlQuery.Select.Add(column);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
145 ColumnIndexes.Add(column, idx);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
146 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
147
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
148 return idx;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
149 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
150
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
151 public override int ConvertToParentIndex(int index, IBuildContext context)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
152 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
153 var idx = GetIndex(context.SqlQuery.Select.Columns[index]);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
154 return Parent == null ? idx : Parent.ConvertToParentIndex(idx, this);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
155 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
156
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
157 public override void SetAlias(string alias)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
158 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
159 if (alias.Contains('<'))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
160 return;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
161
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
162 if (SqlQuery.From.Tables[0].Alias == null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
163 SqlQuery.From.Tables[0].Alias = alias;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
164 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
165
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
166 public override ISqlExpression GetSubQuery(IBuildContext context)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
167 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
168 return null;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
169 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
170 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
171 }