Mercurial > pub > bltoolkit
comparison Source/Data/Linq/Builder/ContainsBuilder.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.Expressions; | |
3 | |
4 namespace BLToolkit.Data.Linq.Builder | |
5 { | |
6 using BLToolkit.Linq; | |
7 using Data.Sql; | |
8 | |
9 class ContainsBuilder : MethodCallBuilder | |
10 { | |
11 protected override bool CanBuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) | |
12 { | |
13 return methodCall.IsQueryable("Contains") && methodCall.Arguments.Count == 2; | |
14 } | |
15 | |
16 protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) | |
17 { | |
18 var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0])); | |
19 return new ContainsContext(buildInfo.Parent, methodCall, sequence); | |
20 } | |
21 | |
22 protected override SequenceConvertInfo Convert( | |
23 ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo, ParameterExpression param) | |
24 { | |
25 return null; | |
26 } | |
27 | |
28 class ContainsContext : SequenceContextBase | |
29 { | |
30 readonly MethodCallExpression _methodCall; | |
31 | |
32 public ContainsContext(IBuildContext parent, MethodCallExpression methodCall, IBuildContext sequence) | |
33 : base(parent, sequence, null) | |
34 { | |
35 _methodCall = methodCall; | |
36 } | |
37 | |
38 public override void BuildQuery<T>(Query<T> query, ParameterExpression queryParameter) | |
39 { | |
40 var sql = GetSubQuery(null); | |
41 | |
42 query.Queries[0].SqlQuery = new SqlQuery(); | |
43 query.Queries[0].SqlQuery.Select.Add(sql); | |
44 | |
45 var expr = Builder.BuildSql(typeof(bool), 0); | |
46 var mapper = Builder.BuildMapper<object>(expr); | |
47 | |
48 query.SetElementQuery(mapper.Compile()); | |
49 } | |
50 | |
51 public override Expression BuildExpression(Expression expression, int level) | |
52 { | |
53 var idx = ConvertToIndex(expression, level, ConvertFlags.Field); | |
54 return Builder.BuildSql(typeof(bool), idx[0].Index); | |
55 } | |
56 | |
57 public override SqlInfo[] ConvertToSql(Expression expression, int level, ConvertFlags flags) | |
58 { | |
59 if (expression == null) | |
60 { | |
61 var sql = GetSubQuery(null); | |
62 var query = SqlQuery; | |
63 | |
64 if (Parent != null) | |
65 query = Parent.SqlQuery; | |
66 | |
67 return new[] { new SqlInfo { Query = query, Sql = sql } }; | |
68 } | |
69 | |
70 throw new InvalidOperationException(); | |
71 } | |
72 | |
73 public override SqlInfo[] ConvertToIndex(Expression expression, int level, ConvertFlags flags) | |
74 { | |
75 var sql = ConvertToSql(expression, level, flags); | |
76 | |
77 if (sql[0].Index < 0) | |
78 sql[0].Index = sql[0].Query.Select.Add(sql[0].Sql); | |
79 | |
80 return sql; | |
81 } | |
82 | |
83 public override IsExpressionResult IsExpression(Expression expression, int level, RequestFor requestFlag) | |
84 { | |
85 if (expression == null) | |
86 { | |
87 switch (requestFlag) | |
88 { | |
89 case RequestFor.Expression : | |
90 case RequestFor.Field : return IsExpressionResult.False; | |
91 } | |
92 } | |
93 | |
94 throw new InvalidOperationException(); | |
95 } | |
96 | |
97 public override IBuildContext GetContext(Expression expression, int level, BuildInfo buildInfo) | |
98 { | |
99 throw new InvalidOperationException(); | |
100 } | |
101 | |
102 ISqlExpression _subQuerySql; | |
103 | |
104 public override ISqlExpression GetSubQuery(IBuildContext context) | |
105 { | |
106 if (_subQuerySql == null) | |
107 { | |
108 var args = _methodCall.Method.GetGenericArguments(); | |
109 var param = Expression.Parameter(args[0], "param"); | |
110 var expr = _methodCall.Arguments[1]; | |
111 var condition = Expression.Lambda(Expression.Equal(param, expr), param); | |
112 | |
113 IBuildContext ctx = new ExpressionContext(Parent, Sequence, condition); | |
114 | |
115 ctx = Builder.GetContext(ctx, expr) ?? ctx; | |
116 | |
117 Builder.ReplaceParent(ctx, this); | |
118 | |
119 SqlQuery.Condition cond; | |
120 | |
121 if (Sequence.SqlQuery != SqlQuery && | |
122 (ctx.IsExpression(expr, 0, RequestFor.Field). Result || | |
123 ctx.IsExpression(expr, 0, RequestFor.Expression).Result)) | |
124 { | |
125 Sequence.ConvertToIndex(null, 0, ConvertFlags.All); | |
126 var ex = Builder.ConvertToSql(ctx, _methodCall.Arguments[1], false); | |
127 cond = new SqlQuery.Condition(false, new SqlQuery.Predicate.InSubQuery(ex, false, SqlQuery)); | |
128 } | |
129 else | |
130 { | |
131 var sequence = Builder.BuildWhere(Parent, Sequence, condition, true); | |
132 cond = new SqlQuery.Condition(false, new SqlQuery.Predicate.FuncLike(SqlFunction.CreateExists(sequence.SqlQuery))); | |
133 } | |
134 | |
135 _subQuerySql = new SqlQuery.SearchCondition(cond); | |
136 } | |
137 | |
138 return _subQuerySql; | |
139 } | |
140 } | |
141 } | |
142 } |