From 8ef888e8fc3ad081d38d0354ea368bf5bd5fb92c Mon Sep 17 00:00:00 2001 From: mcintyre321 Date: Fri, 5 Sep 2014 11:48:19 +0100 Subject: [PATCH] Allow custom count query --- LinqToAnything.Tests/Tests.cs | 10 ++++++++++ LinqToAnything/DataQuery.cs | 1 + LinqToAnything/DelegateQueryable.cs | 9 +++++---- LinqToAnything/Extension.cs | 19 ------------------- LinqToAnything/LinqToAnything.csproj | 1 - LinqToAnything/QueryProvider.cs | 20 ++++++++++++++------ 6 files changed, 30 insertions(+), 30 deletions(-) delete mode 100644 LinqToAnything/Extension.cs diff --git a/LinqToAnything.Tests/Tests.cs b/LinqToAnything.Tests/Tests.cs index be08dac..7cd48f6 100644 --- a/LinqToAnything.Tests/Tests.cs +++ b/LinqToAnything.Tests/Tests.cs @@ -293,6 +293,16 @@ public void CanHandleAProjectionASkipAndAnOrderByAsc() var pq = new DelegateQueryable(getPageFromDataSource); pq.OrderBy(e => e.Name).ToArray(); } + [Test] + public void CanDoAnOptimizedCount() + { + DataQuery getPageFromDataSource = (info) => + { + throw new NotImplementedException(); + }; + var pq = new DelegateQueryable(getPageFromDataSource, qi => 15); + Assert.AreEqual(15, pq.Count(x => x.Index > 1)); + } diff --git a/LinqToAnything/DataQuery.cs b/LinqToAnything/DataQuery.cs index a2f11f6..eff4fa2 100644 --- a/LinqToAnything/DataQuery.cs +++ b/LinqToAnything/DataQuery.cs @@ -3,4 +3,5 @@ namespace LinqToAnything { public delegate IEnumerable DataQuery(QueryInfo info); + public delegate int CountQuery(QueryInfo info); } \ No newline at end of file diff --git a/LinqToAnything/DelegateQueryable.cs b/LinqToAnything/DelegateQueryable.cs index 1e6a077..1e919b8 100644 --- a/LinqToAnything/DelegateQueryable.cs +++ b/LinqToAnything/DelegateQueryable.cs @@ -11,16 +11,17 @@ public class DelegateQueryable : IOrderedQueryable QueryProvider provider; Expression expression; - public DelegateQueryable(DataQuery dataQuery) + public DelegateQueryable(DataQuery dataQuery, CountQuery countQuery = null) { - this.provider = new QueryProvider(dataQuery); + + this.provider = new QueryProvider(dataQuery, countQuery ?? (qi => dataQuery(qi).Count())); this.expression = Expression.Constant(this); } - public DelegateQueryable(DataQuery dataQuery, Expression expression, QueryVisitor ev) + internal DelegateQueryable(DataQuery dataQuery, CountQuery countQuery, Expression expression, QueryVisitor ev) { - this.provider = new QueryProvider(dataQuery, ev); + this.provider = new QueryProvider(dataQuery, countQuery, ev); this.expression = expression ?? Expression.Constant(this); } diff --git a/LinqToAnything/Extension.cs b/LinqToAnything/Extension.cs deleted file mode 100644 index c2d72ca..0000000 --- a/LinqToAnything/Extension.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System.Linq; - -namespace LinqToAnything -{ - public static class Extension - { - public static IQueryable ToDelegateQueryable(this IQueryable inner) - { - DataQuery query = info => - { - var q = inner; - if (info.Skip > 0) q = q.Skip(info.Skip); - if (info.Take.HasValue) q = q.Take(info.Take.Value); - return q; - }; - return new DelegateQueryable(query); - } - } -} diff --git a/LinqToAnything/LinqToAnything.csproj b/LinqToAnything/LinqToAnything.csproj index a38c0e4..2af28a9 100644 --- a/LinqToAnything/LinqToAnything.csproj +++ b/LinqToAnything/LinqToAnything.csproj @@ -49,7 +49,6 @@ - diff --git a/LinqToAnything/QueryProvider.cs b/LinqToAnything/QueryProvider.cs index 40594e2..139902e 100644 --- a/LinqToAnything/QueryProvider.cs +++ b/LinqToAnything/QueryProvider.cs @@ -9,13 +9,15 @@ namespace LinqToAnything public class QueryProvider : IQueryProvider { private readonly DataQuery _dataQuery; + private readonly CountQuery countQuery; private QueryVisitor _queryVisitor; - public QueryProvider(DataQuery dataQuery, QueryVisitor _queryVisitor = null) + public QueryProvider(DataQuery dataQuery, CountQuery countQuery, QueryVisitor queryVisitor = null) { _dataQuery = dataQuery; - this._queryVisitor = _queryVisitor ?? new QueryVisitor(); + this.countQuery = countQuery; + this._queryVisitor = queryVisitor ?? new QueryVisitor(); } public IQueryable CreateQuery(Expression expression) @@ -30,9 +32,9 @@ public IQueryable CreateQuery(Expression expression) if (typeof(TElement) != typeof(T)) { DataQuery q = info => _dataQuery(info).Select(queryVisitor.Transform()); - return new DelegateQueryable(q, null, queryVisitor); + return new DelegateQueryable(q, countQuery, null, queryVisitor); } - return new DelegateQueryable((DataQuery)((object)_dataQuery), expression, queryVisitor); + return new DelegateQueryable((DataQuery)((object)_dataQuery), countQuery, expression, queryVisitor); } @@ -41,9 +43,9 @@ public IEnumerable GetEnumerable() { var queryVisitor = new QueryVisitor(_queryVisitor.QueryInfo.Clone()); var results = _dataQuery(queryVisitor.QueryInfo); - //if (queryVisitor.Select != null) + //if (countQuery.Select != null) //{ - // var projectionFunc = (Func)queryVisitor.Select.Lambda.Compile(); + // var projectionFunc = (Func)countQuery.Select.Lambda.Compile(); // return results.Select(projectionFunc); //} return (IEnumerable) results; @@ -57,8 +59,14 @@ object IQueryProvider.Execute(Expression expression) public TResult Execute(Expression expression) { var methodCallExpression = (MethodCallExpression)expression; + var queryVisitor = new QueryVisitor(_queryVisitor.QueryInfo.Clone()); queryVisitor.Visit(expression); + if (methodCallExpression.Method.Name == "Count" && typeof(TResult) == typeof(int)) + { + return (TResult) (object) countQuery(queryVisitor.QueryInfo); + } + var array = _dataQuery(queryVisitor.QueryInfo).ToList(); var data = array.AsQueryable();