diff Source/Data/Linq/Builder/AllAnyBuilder.cs @ 0:f990fcb411a9

Копия текущей версии из github
author cin
date Thu, 27 Mar 2014 21:46:09 +0400
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Source/Data/Linq/Builder/AllAnyBuilder.cs	Thu Mar 27 21:46:09 2014 +0400
@@ -0,0 +1,161 @@
+using System;
+using System.Linq.Expressions;
+
+namespace BLToolkit.Data.Linq.Builder
+{
+	using BLToolkit.Linq;
+	using Data.Sql;
+
+	class AllAnyBuilder : MethodCallBuilder
+	{
+		protected override bool CanBuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
+		{
+			return methodCall.IsQueryable("All", "Any");
+		}
+
+		protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
+		{
+			var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0]) { CopyTable = true });
+
+			if (methodCall.Arguments.Count == 2)
+			{
+				var condition = (LambdaExpression)methodCall.Arguments[1].Unwrap();
+
+				if (methodCall.Method.Name == "All")
+#if FW4 || SILVERLIGHT
+					condition = Expression.Lambda(Expression.Not(condition.Body), condition.Name, condition.Parameters);
+#else
+					condition = Expression.Lambda(Expression.Not(condition.Body), condition.Parameters.ToArray());
+#endif
+
+				sequence = builder.BuildWhere(buildInfo.Parent, sequence, condition, true);
+				sequence.SetAlias(condition.Parameters[0].Name);
+			}
+
+			return new AllAnyContext(buildInfo.Parent, methodCall, sequence);
+		}
+
+		protected override SequenceConvertInfo Convert(
+			ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo, ParameterExpression param)
+		{
+			if (methodCall.Arguments.Count == 2)
+			{
+				var predicate = (LambdaExpression)methodCall.Arguments[1].Unwrap();
+				var info      = builder.ConvertSequence(new BuildInfo(buildInfo, methodCall.Arguments[0]), predicate.Parameters[0]);
+
+				if (info != null)
+				{
+					info.Expression = methodCall.Convert(ex => ConvertMethod(methodCall, 0, info, predicate.Parameters[0], ex));
+					info.Parameter  = param;
+
+					return info;
+				}
+			}
+			else
+			{
+				var info = builder.ConvertSequence(new BuildInfo(buildInfo, methodCall.Arguments[0]), null);
+
+				if (info != null)
+				{
+					info.Expression = methodCall.Convert(ex => ConvertMethod(methodCall, 0, info, null, ex));
+					info.Parameter  = param;
+
+					return info;
+				}
+			}
+
+			return null;
+		}
+
+		class AllAnyContext : SequenceContextBase
+		{
+			readonly MethodCallExpression _methodCall;
+
+			public AllAnyContext(IBuildContext parent, MethodCallExpression methodCall, IBuildContext sequence)
+				: base(parent, sequence, null)
+			{
+				_methodCall = methodCall;
+			}
+
+			public override void BuildQuery<T>(Query<T> query, ParameterExpression queryParameter)
+			{
+				var sql = GetSubQuery(null);
+
+				query.Queries[0].SqlQuery = new SqlQuery();
+				query.Queries[0].SqlQuery.Select.Add(sql);
+
+				var expr   = Builder.BuildSql(typeof(bool), 0);
+				var mapper = Builder.BuildMapper<object>(expr);
+
+				query.SetElementQuery(mapper.Compile());
+			}
+
+			public override Expression BuildExpression(Expression expression, int level)
+			{
+				var idx = ConvertToIndex(expression, level, ConvertFlags.Field);
+				return Builder.BuildSql(typeof(bool), idx[0].Index);
+			}
+
+			public override SqlInfo[] ConvertToSql(Expression expression, int level, ConvertFlags flags)
+			{
+				if (expression == null)
+				{
+					var sql   = GetSubQuery(null);
+					var query = SqlQuery;
+
+					if (Parent != null)
+						query = Parent.SqlQuery;
+
+					return new[] { new SqlInfo { Query = query, Sql = sql } };
+				}
+
+				throw new InvalidOperationException();
+			}
+
+			public override SqlInfo[] ConvertToIndex(Expression expression, int level, ConvertFlags flags)
+			{
+				var sql = ConvertToSql(expression, level, flags);
+
+				if (sql[0].Index < 0)
+					sql[0].Index = sql[0].Query.Select.Add(sql[0].Sql);
+
+				return sql;
+			}
+
+			public override IsExpressionResult IsExpression(Expression expression, int level, RequestFor requestFlag)
+			{
+				if (expression == null)
+				{
+					switch (requestFlag)
+					{
+						case RequestFor.Expression :
+						case RequestFor.Field      : return IsExpressionResult.False;
+					}
+				}
+
+				throw new InvalidOperationException();
+			}
+
+			public override IBuildContext GetContext(Expression expression, int level, BuildInfo buildInfo)
+			{
+				throw new InvalidOperationException();
+			}
+
+			ISqlExpression _subQuerySql;
+
+			public override ISqlExpression GetSubQuery(IBuildContext context)
+			{
+				if (_subQuerySql == null)
+				{
+					var cond = new SqlQuery.Condition(
+						_methodCall.Method.Name == "All",
+						new SqlQuery.Predicate.FuncLike(SqlFunction.CreateExists(SqlQuery)));
+
+					_subQuerySql = new SqlQuery.SearchCondition(cond);
+				}
+
+				return _subQuerySql;
+			}
+		}
+	}
+}