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