22using  System ; 
33using  System . Collections . Generic ; 
44using  System . Data ; 
5- using  System . Data . SqlClient ; 
65using  System . Linq ; 
6+ using  System . Text ; 
77using  System . Web . Helpers ; 
88
99namespace  Griddly . Mvc 
@@ -19,6 +19,7 @@ public class DapperGriddlyResult<T> : GriddlyResult<T>
1919
2020        long ?  _overallCount  =  null ; 
2121        bool  _fixedSort ; 
22+         static readonly  bool  _hasOverallCount  =  typeof ( IHasOverallCount ) . IsAssignableFrom ( typeof ( T ) ) ; 
2223
2324        public  DapperGriddlyResult ( Func < IDbConnection >  getConnection ,  string  sql ,  object  param ,  Func < IDbConnection ,  IDbTransaction ,  string ,  object ,  IEnumerable < T > >  map  =  null ,  Action < IDbConnection ,  IDbTransaction ,  IList < T > >  massage  =  null ,  bool  fixedSort  =  false ,  Func < IDbTransaction >  getTransaction  =  null ) 
2425            :  base ( null ) 
@@ -35,6 +36,46 @@ public DapperGriddlyResult(Func<IDbConnection> getConnection, string sql, object
3536            _massage  =  massage ; 
3637            _fixedSort  =  fixedSort ; 
3738            _getTransaction  =  getTransaction ; 
39+ 
40+         } 
41+ 
42+         public  override  void  PopulateSummaryValues ( GriddlySettings < T >  settings ) 
43+         { 
44+             List < GriddlyColumn >  summaryColumns  =  settings . Columns . Where ( x =>  x . SummaryFunction  !=  null ) . ToList ( ) ; 
45+ 
46+             if  ( summaryColumns . Any ( ) ) 
47+             { 
48+                 StringBuilder  aggregateExpression  =  new  StringBuilder ( ) ; 
49+ 
50+                 aggregateExpression . Append ( "SELECT " ) ; 
51+ 
52+                 for  ( int  i  =  0 ;  i  <  summaryColumns . Count ;  i ++ ) 
53+                 { 
54+                     if  ( i  >  0 ) 
55+                         aggregateExpression . Append ( ", " ) ; 
56+ 
57+                     GriddlyColumn  col  =  summaryColumns [ i ] ; 
58+ 
59+                     aggregateExpression . AppendFormat ( "{0}({1}) AS _a{2}" ,  col . SummaryFunction ,  col . ExpressionString ,  i ) ; 
60+                 } 
61+ 
62+                 string  sql  =  string . Format ( "{0} FROM ({1}) [_proj]" ,  aggregateExpression . ToString ( ) ,  _sql ) ; 
63+ 
64+                 try 
65+                 { 
66+                     IDbConnection  cn  =  _getConnection ( ) ; 
67+                     IDbTransaction  tx  =  _getTransaction  !=  null  ?  _getTransaction ( )  :  null ; 
68+ 
69+                     IDictionary < string ,  object >  item  =  cn . Query ( sql ,  _param ,  tx ) . Single ( ) ; 
70+ 
71+                     for  ( int  i  =  0 ;  i  <  summaryColumns . Count ;  i ++ ) 
72+                         summaryColumns [ i ] . SummaryValue  =  item [ "_a"  +  i ] ; 
73+                 } 
74+                 catch  ( Exception  ex ) 
75+                 { 
76+                     throw  new  DapperGriddlyException ( "Error populating summary values." ,  sql ,  _param ,  ex ) ; 
77+                 } 
78+             } 
3879        } 
3980
4081        public  override  long  GetCount ( ) 
@@ -62,7 +103,22 @@ public override long GetCount()
62103
63104        public  override  IList < T >  GetPage ( int  pageNumber ,  int  pageSize ,  SortField [ ]  sortFields ) 
64105        { 
65-             string  sql  =  string . Format ( "{0} "  +  ( _fixedSort  ?  ""  :  "ORDER BY {1}" )  +  " OFFSET {2} ROWS FETCH NEXT {3} ROWS ONLY" ,  _sql ,  BuildSortClause ( sortFields ) ,  pageNumber  *  pageSize ,  pageSize ) ; 
106+             string  format ; 
107+ 
108+             if  ( ! _hasOverallCount  ||  _sql . IndexOf ( "OverallCount" ,  StringComparison . InvariantCultureIgnoreCase )  !=  - 1 ) 
109+                 format  =  "{0} "  +  ( _fixedSort  ?  ""  :  "ORDER BY {1}" )  +  " OFFSET {2} ROWS FETCH NEXT {3} ROWS ONLY" ; 
110+             else 
111+                 // TODO: use dapper multimap Query<T, Dictionary<string, object>> to map all summary values in one go 
112+                 format  =  @" 
113+ ;WITH _data AS ( 
114+     {0} 
115+ ), 
116+     _count AS ( 
117+         SELECT COUNT(0) AS OverallCount FROM _data 
118+ ) 
119+ SELECT * FROM _data CROSS APPLY _count "  +  ( _fixedSort  ?  ""  :  "ORDER BY {1}" )  +  " OFFSET {2} ROWS FETCH NEXT {3} ROWS ONLY" ; 
120+ 
121+             string  sql  =  string . Format ( format ,  _sql ,  BuildSortClause ( sortFields ) ,  pageNumber  *  pageSize ,  pageSize ) ; 
66122
67123            return  ExecuteQuery ( sql ,  _param ) ; 
68124        } 
@@ -88,10 +144,14 @@ IList<T> ExecuteQuery(string sql, object param)
88144            try 
89145            { 
90146                IEnumerable < T >  result  =  _map ( _getConnection ( ) ,  _getTransaction  !=  null  ?  _getTransaction ( )  :  null ,  sql ,  param ) ; 
91-                 IHasOverallCount  overallCount  =  result  as  IHasOverallCount ; 
92147
93-                 if  ( overallCount  !=  null ) 
94-                     _overallCount  =  overallCount . OverallCount ; 
148+                 if  ( _hasOverallCount ) 
149+                 { 
150+                     IHasOverallCount  overallCount  =  result  as  IHasOverallCount ; 
151+ 
152+                     if  ( overallCount  !=  null ) 
153+                         _overallCount  =  overallCount . OverallCount ; 
154+                 } 
95155
96156                IList < T >  results  =  result . ToList ( ) ; 
97157
@@ -110,7 +170,7 @@ protected IEnumerable<T> DefaultMap(IDbConnection cn, IDbTransaction tx, string
110170        { 
111171            IEnumerable < T >  result  =  cn . Query < T > ( sql ,  param ,  tx ) ; 
112172
113-             if  ( typeof ( IHasOverallCount ) . IsAssignableFrom ( typeof ( T ) ) ) 
173+             if  ( _hasOverallCount ) 
114174            { 
115175                IHasOverallCount  firstRow  =  result . FirstOrDefault ( )  as  IHasOverallCount ; 
116176                ListPage < T >  lp  =  new  ListPage < T > ( ) ; 
0 commit comments