Mercurial > pub > bltoolkit
comparison Source/Data/Linq/Builder/TakeSkipBuilder.cs @ 0:f990fcb411a9
Копия текущей версии из github
author | cin |
---|---|
date | Thu, 27 Mar 2014 21:46:09 +0400 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:f990fcb411a9 |
---|---|
1 using System; | |
2 using System.Collections.Generic; | |
3 using System.Linq; | |
4 using System.Linq.Expressions; | |
5 | |
6 namespace BLToolkit.Data.Linq.Builder | |
7 { | |
8 using BLToolkit.Linq; | |
9 using Data.Sql; | |
10 | |
11 class TakeSkipBuilder : MethodCallBuilder | |
12 { | |
13 protected override bool CanBuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) | |
14 { | |
15 return methodCall.IsQueryable("Skip", "Take"); | |
16 } | |
17 | |
18 protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) | |
19 { | |
20 var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0])); | |
21 | |
22 var arg = methodCall.Arguments[1].Unwrap(); | |
23 | |
24 if (arg.NodeType == ExpressionType.Lambda) | |
25 arg = ((LambdaExpression)arg).Body.Unwrap(); | |
26 | |
27 var expr = builder.ConvertToSql(sequence, arg, false); | |
28 | |
29 if (methodCall.Method.Name == "Take") | |
30 { | |
31 BuildTake(builder, sequence, expr); | |
32 } | |
33 else | |
34 { | |
35 BuildSkip(builder, sequence, sequence.SqlQuery.Select.SkipValue, expr); | |
36 } | |
37 | |
38 return sequence; | |
39 } | |
40 | |
41 protected override SequenceConvertInfo Convert( | |
42 ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo, ParameterExpression param) | |
43 { | |
44 var info = builder.ConvertSequence(new BuildInfo(buildInfo, methodCall.Arguments[0]), null); | |
45 | |
46 if (info != null) | |
47 { | |
48 info.Expression = | |
49 Expression.Call( | |
50 methodCall.Method.DeclaringType, | |
51 methodCall.Method.Name, | |
52 new[] { info.Expression.Type.GetGenericArguments()[0] }, | |
53 info.Expression, methodCall.Arguments[1]); | |
54 info.Parameter = param; | |
55 | |
56 return info; | |
57 } | |
58 | |
59 return null; | |
60 } | |
61 | |
62 static void BuildTake(ExpressionBuilder builder, IBuildContext sequence, ISqlExpression expr) | |
63 { | |
64 var sql = sequence.SqlQuery; | |
65 | |
66 builder.SqlProvider.SqlQuery = sql; | |
67 | |
68 sql.Select.Take(expr); | |
69 | |
70 if (sql.Select.SkipValue != null && builder.SqlProvider.IsTakeSupported && !builder.SqlProvider.IsSkipSupported) | |
71 { | |
72 if (sql.Select.SkipValue is SqlParameter && sql.Select.TakeValue is SqlValue) | |
73 { | |
74 var skip = (SqlParameter)sql.Select.SkipValue; | |
75 var parm = (SqlParameter)sql.Select.SkipValue.Clone(new Dictionary<ICloneableElement,ICloneableElement>(), _ => true); | |
76 | |
77 parm.SetTakeConverter((int)((SqlValue)sql.Select.TakeValue).Value); | |
78 | |
79 sql.Select.Take(parm); | |
80 | |
81 var ep = (from pm in builder.CurrentSqlParameters where pm.SqlParameter == skip select pm).First(); | |
82 | |
83 ep = new ParameterAccessor | |
84 { | |
85 Expression = ep.Expression, | |
86 Accessor = ep.Accessor, | |
87 SqlParameter = parm | |
88 }; | |
89 | |
90 builder.CurrentSqlParameters.Add(ep); | |
91 } | |
92 else | |
93 sql.Select.Take(builder.Convert( | |
94 sequence, | |
95 new SqlBinaryExpression(typeof(int), sql.Select.SkipValue, "+", sql.Select.TakeValue, Precedence.Additive))); | |
96 } | |
97 | |
98 if (!builder.SqlProvider.TakeAcceptsParameter) | |
99 { | |
100 var p = sql.Select.TakeValue as SqlParameter; | |
101 | |
102 if (p != null) | |
103 p.IsQueryParameter = false; | |
104 } | |
105 } | |
106 | |
107 static void BuildSkip(ExpressionBuilder builder, IBuildContext sequence, ISqlExpression prevSkipValue, ISqlExpression expr) | |
108 { | |
109 var sql = sequence.SqlQuery; | |
110 | |
111 builder.SqlProvider.SqlQuery = sql; | |
112 | |
113 sql.Select.Skip(expr); | |
114 | |
115 builder.SqlProvider.SqlQuery = sql; | |
116 | |
117 if (sql.Select.TakeValue != null) | |
118 { | |
119 if (builder.SqlProvider.IsSkipSupported || !builder.SqlProvider.IsTakeSupported) | |
120 sql.Select.Take(builder.Convert( | |
121 sequence, | |
122 new SqlBinaryExpression(typeof(int), sql.Select.TakeValue, "-", sql.Select.SkipValue, Precedence.Additive))); | |
123 | |
124 if (prevSkipValue != null) | |
125 sql.Select.Skip(builder.Convert( | |
126 sequence, | |
127 new SqlBinaryExpression(typeof(int), prevSkipValue, "+", sql.Select.SkipValue, Precedence.Additive))); | |
128 } | |
129 | |
130 if (!builder.SqlProvider.TakeAcceptsParameter) | |
131 { | |
132 var p = sql.Select.SkipValue as SqlParameter; | |
133 | |
134 if (p != null) | |
135 p.IsQueryParameter = false; | |
136 } | |
137 } | |
138 } | |
139 } |