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 }