@@ -105,7 +105,7 @@ public static async Task<PagedResponse<TDto>> FilterOrderAndGetPagedAsync<TEntit
105105 . Select ( selectExpression )
106106 . ApplyPaging ( model . Page , model . PageSize )
107107 . ToListAsync ( cancellationToken ) ;
108-
108+
109109 return new PagedResponse < TDto > ( data , model . Page , model . PageSize , totalCount ) ;
110110 }
111111
@@ -184,7 +184,8 @@ public static async Task<PagedResponse<object>> ColumnDistinctValuesAsync<TEntit
184184 return new PagedResponse < object > ( [ decrypted ] , 1 , 1 , 1 ) ;
185185 }
186186
187- public static async Task < CursoredResponse < object > > ColumnDistinctValuesAsync < TEntity > ( this IQueryable < TEntity > query ,
187+ public static async Task < CursoredResponse < object ? > > ColumnDistinctValuesAsync < TEntity > (
188+ this IQueryable < TEntity > query ,
188189 ColumnDistinctValueCursoredQueryModel model ,
189190 Func < byte [ ] , string > ? decryptor = default ,
190191 CancellationToken cancellationToken = default )
@@ -195,32 +196,79 @@ public static async Task<CursoredResponse<object>> ColumnDistinctValuesAsync<TEn
195196
196197 if ( ! mapper . IsEncrypted ( model . PropertyName ) )
197198 {
198- var result = await query
199- . ApplyFiltering ( gridifyModel , mapper )
200- . ApplySelect ( model . PropertyName , mapper )
199+ var baseQuery = query
200+ . ApplyFiltering ( gridifyModel , mapper )
201+ . ApplySelect ( model . PropertyName , mapper ) ;
202+
203+ var filterEmpty = string . IsNullOrWhiteSpace ( gridifyModel . Filter ) ;
204+ var hasNull = false ;
205+ var take = model . PageSize ;
206+
207+ if ( filterEmpty )
208+ {
209+ // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract
210+ hasNull = await baseQuery . AnyAsync ( x => x == null , cancellationToken ) ;
211+ if ( hasNull && take > 0 )
212+ {
213+ take -= 1 ;
214+ }
215+ }
216+
217+ var result = await baseQuery
201218 . Distinct ( )
202219 . OrderBy ( x => x )
203- . Take ( model . PageSize )
220+ . Take ( take )
204221 . ToListAsync ( cancellationToken ) ;
205222
206- return new CursoredResponse < object > ( result , model . PageSize ) ;
223+ if ( ! filterEmpty || ! hasNull )
224+ {
225+ return new CursoredResponse < object ? > ( result ! , model . PageSize ) ;
226+ }
227+
228+ if ( result . Count > 0 && ReferenceEquals ( result [ ^ 1 ] , null ) )
229+ {
230+ result . RemoveAt ( result . Count - 1 ) ;
231+ }
232+
233+ result . Insert ( 0 , null ! ) ;
234+ return new CursoredResponse < object ? > ( result ! , model . PageSize ) ;
207235 }
208236
209- var item = await query
210- . ApplyFiltering ( gridifyModel , mapper )
211- . Select ( CreateSelector < TEntity > ( model . PropertyName ) )
212- . FirstOrDefaultAsync ( cancellationToken ) ;
237+ // Encrypted (byte[]) path:
238+ var encryptedQuery = query
239+ . ApplyFiltering ( gridifyModel , mapper )
240+ . Select ( CreateSelector < TEntity > ( model . PropertyName ) ) ;
213241
214- if ( item is null || string . IsNullOrEmpty ( model . Filter ) )
215- return new CursoredResponse < object > ( [ ] , model . PageSize ) ;
242+ if ( string . IsNullOrWhiteSpace ( model . Filter ) )
243+ {
244+ // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract
245+ var hasNull = await encryptedQuery . AnyAsync ( x => x == null , cancellationToken ) ;
246+
247+ if ( hasNull )
248+ return new CursoredResponse < object ? > ( [ null ] ,
249+ model . PageSize ) ;
250+
251+ return new CursoredResponse < object ? > ( [ ] , model . PageSize ) ;
252+ }
253+
254+ var item = await encryptedQuery . FirstOrDefaultAsync ( cancellationToken ) ;
255+ if ( item is null )
256+ {
257+ return new CursoredResponse < object ? > ( [ ] , model . PageSize ) ;
258+ }
216259
217260 if ( decryptor is null )
218261 {
219262 throw new KeyNotFoundException ( "Decryptor is required for encrypted properties." ) ;
220263 }
221264
222- var decrypted = decryptor ( ( byte [ ] ) item ) ;
223- return new CursoredResponse < object > ( [ decrypted ] , model . PageSize ) ;
265+ if ( item is not byte [ ] bytes )
266+ {
267+ throw new InvalidCastException ( "Encrypted selector did not return a byte[] value." ) ;
268+ }
269+
270+ var decrypted = decryptor ( bytes ) ;
271+ return new CursoredResponse < object ? > ( [ decrypted ] , model . PageSize ) ;
224272 }
225273
226274 // ---------- Aggregation ----------
0 commit comments