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