diff Source/Data/Linq/Builder/OrderByBuilder.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/OrderByBuilder.cs	Thu Mar 27 21:46:09 2014 +0400
@@ -0,0 +1,68 @@
+using System;
+using System.Linq;
+using System.Linq.Expressions;
+
+namespace BLToolkit.Data.Linq.Builder
+{
+	using BLToolkit.Linq;
+
+	class OrderByBuilder : MethodCallBuilder
+	{
+		protected override bool CanBuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
+		{
+			if (!methodCall.IsQueryable("OrderBy", "OrderByDescending", "ThenBy", "ThenByDescending"))
+				return false;
+
+			var body = ((LambdaExpression)methodCall.Arguments[1].Unwrap()).Body.Unwrap();
+
+			if (body.NodeType == ExpressionType.MemberInit)
+			{
+				var mi = (MemberInitExpression)body;
+				bool throwExpr;
+
+				if (mi.NewExpression.Arguments.Count > 0 || mi.Bindings.Count == 0)
+					throwExpr = true;
+				else
+					throwExpr = mi.Bindings.Any(b => b.BindingType != MemberBindingType.Assignment);
+
+				if (throwExpr)
+					throw new NotSupportedException(string.Format("Explicit construction of entity type '{0}' in order by is not allowed.", body.Type));
+			}
+
+			return true;
+		}
+
+		protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
+		{
+			var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0]));
+
+			if (sequence.SqlQuery.Select.TakeValue != null || sequence.SqlQuery.Select.SkipValue != null)
+				sequence = new SubQueryContext(sequence);
+
+			var lambda  = (LambdaExpression)methodCall.Arguments[1].Unwrap();
+			var sparent = sequence.Parent;
+			var order   = new ExpressionContext(buildInfo.Parent, sequence, lambda);
+			var body    = lambda.Body.Unwrap();
+			var sql     = builder.ConvertExpressions(order, body, ConvertFlags.Key);
+
+			builder.ReplaceParent(order, sparent);
+
+			if (!methodCall.Method.Name.StartsWith("Then"))
+				sequence.SqlQuery.OrderBy.Items.Clear();
+
+			foreach (var expr in sql)
+			{
+				var e = builder.ConvertSearchCondition(sequence, expr.Sql);
+				sequence.SqlQuery.OrderBy.Expr(e, methodCall.Method.Name.EndsWith("Descending"));
+			}
+
+			return sequence;
+		}
+
+		protected override SequenceConvertInfo Convert(
+			ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo, ParameterExpression param)
+		{
+			return null;
+		}
+	}
+}