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 } |
