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 }