annotate Source/Data/Linq/Builder/FirstSingleBuilder.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.Linq;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
3 using System.Linq.Expressions;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
4
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
5 namespace BLToolkit.Data.Linq.Builder
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
6 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
7 using BLToolkit.Linq;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
8 using Data.Sql;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
9 using Reflection;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
10
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
11 class FirstSingleBuilder : MethodCallBuilder
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
12 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
13 public static string[] MethodNames = new[] { "First", "FirstOrDefault", "Single", "SingleOrDefault" };
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
14
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
15 protected override bool CanBuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
16 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
17 return
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
18 methodCall.IsQueryable(MethodNames) &&
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
19 methodCall.Arguments.Count == 1;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
20 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
21
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
22 protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
23 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
24 var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0]));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
25 var take = 0;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
26
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
27 if (!buildInfo.IsSubQuery || builder.SqlProvider.IsSubQueryTakeSupported)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
28 switch (methodCall.Method.Name)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
29 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
30 case "First" :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
31 case "FirstOrDefault" :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
32 take = 1;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
33 break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
34
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
35 case "Single" :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
36 case "SingleOrDefault" :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
37 if (!buildInfo.IsSubQuery)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
38 take = 2;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
39 break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
40 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
41
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
42 if (take != 0)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
43 builder.BuildTake(sequence, new SqlValue(take));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
44
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
45 return new FirstSingleContext(buildInfo.Parent, sequence, methodCall);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
46 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
47
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
48 protected override SequenceConvertInfo Convert(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
49 ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo, ParameterExpression param)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
50 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
51 if (methodCall.Arguments.Count == 2)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
52 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
53 var predicate = (LambdaExpression)methodCall.Arguments[1].Unwrap();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
54 var info = builder.ConvertSequence(new BuildInfo(buildInfo, methodCall.Arguments[0]), predicate.Parameters[0]);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
55
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
56 if (info != null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
57 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
58 info.Expression = methodCall.Convert(ex => ConvertMethod(methodCall, 0, info, predicate.Parameters[0], ex));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
59 info.Parameter = param;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
60
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
61 return info;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
62 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
63 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
64 else
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
65 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
66 var info = builder.ConvertSequence(new BuildInfo(buildInfo, methodCall.Arguments[0]), null);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
67
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
68 if (info != null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
69 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
70 info.Expression = methodCall.Convert(ex => ConvertMethod(methodCall, 0, info, null, ex));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
71 info.Parameter = param;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
72
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
73 return info;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
74 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
75 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
76
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
77 return null;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
78 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
79
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
80 public class FirstSingleContext : SequenceContextBase
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
81 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
82 public FirstSingleContext(IBuildContext parent, IBuildContext sequence, MethodCallExpression methodCall)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
83 : base(parent, sequence, null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
84 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
85 _methodCall = methodCall;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
86 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
87
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
88 readonly MethodCallExpression _methodCall;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
89
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
90 public override void BuildQuery<T>(Query<T> query, ParameterExpression queryParameter)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
91 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
92 Sequence.BuildQuery(query, queryParameter);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
93
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
94 switch (_methodCall.Method.Name)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
95 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
96 case "First" : query.GetElement = (ctx, db, expr, ps) => query.GetIEnumerable(ctx, db, expr, ps).First(); break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
97 case "FirstOrDefault" : query.GetElement = (ctx, db, expr, ps) => query.GetIEnumerable(ctx, db, expr, ps).FirstOrDefault(); break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
98 case "Single" : query.GetElement = (ctx, db, expr, ps) => query.GetIEnumerable(ctx, db, expr, ps).Single(); break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
99 case "SingleOrDefault" : query.GetElement = (ctx, db, expr, ps) => query.GetIEnumerable(ctx, db, expr, ps).SingleOrDefault(); break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
100 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
101 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
102
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
103 static object SequenceException()
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
104 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
105 return new object[0].First();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
106 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
107
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
108 public override Expression BuildExpression(Expression expression, int level)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
109 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
110 if (expression == null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
111 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
112 if (Builder.SqlProvider.IsApplyJoinSupported && Parent.SqlQuery.GroupBy.IsEmpty)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
113 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
114 var join = SqlQuery.OuterApply(SqlQuery);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
115
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
116 Parent.SqlQuery.From.Tables[0].Joins.Add(join.JoinedTable);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
117
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
118 var expr = Sequence.BuildExpression(expression, level);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
119 var idx = SqlQuery.Select.Add(new SqlValue(1));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
120
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
121 idx = ConvertToParentIndex(idx, this);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
122
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
123 var defaultValue = _methodCall.Method.Name.EndsWith("OrDefault") ?
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
124 Expression.Constant(TypeHelper.GetDefaultValue(expr.Type), expr.Type) as Expression :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
125 Expression.Convert(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
126 Expression.Call(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
127 null,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
128 ReflectionHelper.Expressor<object>.MethodExpressor(_ => SequenceException())),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
129 expr.Type);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
130
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
131 expr = Expression.Condition(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
132 Expression.Call(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
133 ExpressionBuilder.DataReaderParam,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
134 ReflectionHelper.DataReader.IsDBNull,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
135 Expression.Constant(idx)),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
136 defaultValue,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
137 expr);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
138
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
139 return expr;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
140 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
141
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
142 if (Sequence.IsExpression(null, level, RequestFor.Object).Result)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
143 return Builder.BuildMultipleQuery(Parent, _methodCall);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
144
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
145 return Builder.BuildSql(_methodCall.Type, Parent.SqlQuery.Select.Add(SqlQuery));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
146 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
147
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
148 throw new InvalidOperationException();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
149 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
150
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
151 public override SqlInfo[] ConvertToSql(Expression expression, int level, ConvertFlags flags)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
152 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
153 return Sequence.ConvertToSql(expression, level + 1, flags);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
154 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
155
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
156 public override SqlInfo[] ConvertToIndex(Expression expression, int level, ConvertFlags flags)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
157 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
158 return Sequence.ConvertToIndex(expression, level, flags);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
159 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
160
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
161 public override IsExpressionResult IsExpression(Expression expression, int level, RequestFor requestFlag)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
162 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
163 return Sequence.IsExpression(expression, level, requestFlag);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
164 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
165
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
166 public override IBuildContext GetContext(Expression expression, int level, BuildInfo buildInfo)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
167 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
168 throw new InvalidOperationException();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
169 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
170 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
171 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
172 }