Mercurial > pub > bltoolkit
comparison Source/Data/Linq/Builder/DefaultIfEmptyBuilder.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.Linq; | |
| 3 using System.Linq.Expressions; | |
| 4 | |
| 5 namespace BLToolkit.Data.Linq.Builder | |
| 6 { | |
| 7 using BLToolkit.Linq; | |
| 8 using Data.Sql; | |
| 9 | |
| 10 class DefaultIfEmptyBuilder : MethodCallBuilder | |
| 11 { | |
| 12 protected override bool CanBuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) | |
| 13 { | |
| 14 return methodCall.IsQueryable("DefaultIfEmpty"); | |
| 15 } | |
| 16 | |
| 17 protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) | |
| 18 { | |
| 19 var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0])); | |
| 20 var defaultValue = methodCall.Arguments.Count == 1 ? null : methodCall.Arguments[1].Unwrap(); | |
| 21 | |
| 22 if (buildInfo.Parent is SelectManyBuilder.SelectManyContext) | |
| 23 { | |
| 24 var groupJoin = ((SelectManyBuilder.SelectManyContext)buildInfo.Parent).Sequence[0] as JoinBuilder.GroupJoinContext; | |
| 25 | |
| 26 if (groupJoin != null) | |
| 27 { | |
| 28 groupJoin.SqlQuery.From.Tables[0].Joins[0].JoinType = SqlQuery.JoinType.Left; | |
| 29 groupJoin.SqlQuery.From.Tables[0].Joins[0].IsWeak = false; | |
| 30 } | |
| 31 } | |
| 32 | |
| 33 return new DefaultIfEmptyContext(buildInfo.Parent, sequence, defaultValue); | |
| 34 } | |
| 35 | |
| 36 protected override SequenceConvertInfo Convert( | |
| 37 ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo, ParameterExpression param) | |
| 38 { | |
| 39 return null; | |
| 40 } | |
| 41 | |
| 42 public class DefaultIfEmptyContext : SequenceContextBase | |
| 43 { | |
| 44 public DefaultIfEmptyContext(IBuildContext parent, IBuildContext sequence, Expression defaultValue) | |
| 45 : base(parent, sequence, null) | |
| 46 { | |
| 47 _defaultValue = defaultValue; | |
| 48 } | |
| 49 | |
| 50 private readonly Expression _defaultValue; | |
| 51 | |
| 52 public override Expression BuildExpression(Expression expression, int level) | |
| 53 { | |
| 54 var expr = Sequence.BuildExpression(expression, level); | |
| 55 | |
| 56 if (expression == null) | |
| 57 { | |
| 58 var q = | |
| 59 from col in SqlQuery.Select.Columns | |
| 60 where !col.CanBeNull() | |
| 61 select SqlQuery.Select.Columns.IndexOf(col); | |
| 62 | |
| 63 var idx = q.DefaultIfEmpty(-1).First(); | |
| 64 | |
| 65 if (idx == -1) | |
| 66 idx = SqlQuery.Select.Add(new SqlValue((int?) 1)); | |
| 67 | |
| 68 var n = ConvertToParentIndex(idx, this); | |
| 69 | |
| 70 var e = Expression.Call( | |
| 71 ExpressionBuilder.DataReaderParam, | |
| 72 ReflectionHelper.DataReader.IsDBNull, | |
| 73 Expression.Constant(n)) as Expression; | |
| 74 | |
| 75 var defaultValue = _defaultValue ?? Expression.Constant(null, expr.Type); | |
| 76 | |
| 77 #if FW4 || SILVERLIGHT | |
| 78 | |
| 79 if (expr.NodeType == ExpressionType.Parameter) | |
| 80 { | |
| 81 var par = (ParameterExpression)expr; | |
| 82 var pidx = Builder.BlockVariables.IndexOf(par); | |
| 83 | |
| 84 if (pidx >= 0) | |
| 85 { | |
| 86 var ex = Builder.BlockExpressions[pidx]; | |
| 87 | |
| 88 if (ex.NodeType == ExpressionType.Assign) | |
| 89 { | |
| 90 var bex = (BinaryExpression)ex; | |
| 91 | |
| 92 if (bex.Left == expr) | |
| 93 { | |
| 94 if (bex.Right.NodeType != ExpressionType.Conditional) | |
| 95 { | |
| 96 Builder.BlockExpressions[pidx] = | |
| 97 Expression.Assign( | |
| 98 bex.Left, | |
| 99 Expression.Condition(e, defaultValue, bex.Right)); | |
| 100 } | |
| 101 } | |
| 102 } | |
| 103 } | |
| 104 } | |
| 105 | |
| 106 #endif | |
| 107 | |
| 108 expr = Expression.Condition(e, defaultValue, expr); | |
| 109 } | |
| 110 | |
| 111 return expr; | |
| 112 } | |
| 113 | |
| 114 public override SqlInfo[] ConvertToSql(Expression expression, int level, ConvertFlags flags) | |
| 115 { | |
| 116 return Sequence.ConvertToSql(expression, level, flags); | |
| 117 } | |
| 118 | |
| 119 public override SqlInfo[] ConvertToIndex(Expression expression, int level, ConvertFlags flags) | |
| 120 { | |
| 121 return Sequence.ConvertToIndex(expression, level, flags); | |
| 122 } | |
| 123 | |
| 124 public override IsExpressionResult IsExpression(Expression expression, int level, RequestFor requestFlag) | |
| 125 { | |
| 126 return Sequence.IsExpression(expression, level, requestFlag); | |
| 127 } | |
| 128 | |
| 129 public override IBuildContext GetContext(Expression expression, int level, BuildInfo buildInfo) | |
| 130 { | |
| 131 return Sequence.GetContext(expression, level, buildInfo); | |
| 132 } | |
| 133 } | |
| 134 } | |
| 135 } |
