@@ -163,25 +163,34 @@ public static async Task<PagedResponse<object>> ColumnDistinctValuesAsync<TEntit
163163 . Distinct ( )
164164 . OrderBy ( x => x )
165165 . GetPagedAsync ( model , cancellationToken ) ;
166-
167166 return result ;
168167 }
169168
170- var item = await query
171- . ApplyFiltering ( model , mapper )
172- . Select ( CreateSelector < TEntity > ( model . PropertyName ) )
173- . FirstOrDefaultAsync ( cancellationToken ) ;
169+ // Encrypted path (scalar byte[] or IEnumerable<byte[]>), use mapper-driven selection
170+ var encryptedQuery = query
171+ . ApplyFiltering ( model , mapper )
172+ . ApplySelect ( model . PropertyName , mapper ) ; // IQueryable<object?>
174173
175- if ( item is null || string . IsNullOrEmpty ( model . Filter ) )
174+ // Keep original behavior: if no filter, return empty for the obsolete API
175+ if ( string . IsNullOrWhiteSpace ( model . Filter ) )
176+ {
176177 return new PagedResponse < object > ( [ ] , 1 , 1 , 0 ) ;
178+ }
177179
178- if ( decryptor is null )
180+ var selected = await encryptedQuery . FirstOrDefaultAsync ( cancellationToken ) ;
181+ if ( selected is null ) return new PagedResponse < object > ( [ ] , 1 , 1 , 0 ) ;
182+ if ( decryptor is null ) throw new KeyNotFoundException ( "Decryptor is required for encrypted properties." ) ;
183+
184+ object ? decrypted = selected switch
179185 {
180- throw new KeyNotFoundException ( "Decryptor is required for encrypted properties." ) ;
181- }
186+ byte [ ] b => decryptor ( b ) ,
187+ IEnumerable < byte [ ] > bs => bs . FirstOrDefault ( ) is byte [ ] fb ? decryptor ( fb ) : null ,
188+ _ => throw new InvalidCastException ( "Encrypted selector did not return a byte[] or IEnumerable<byte[]> value." )
189+ } ;
182190
183- var decrypted = decryptor ( ( byte [ ] ) item ) ;
184- return new PagedResponse < object > ( [ decrypted ] , 1 , 1 , 1 ) ;
191+ return decrypted is null
192+ ? new PagedResponse < object > ( [ ] , 1 , 1 , 0 )
193+ : new PagedResponse < object > ( [ decrypted ] , 1 , 1 , 1 ) ;
185194 }
186195
187196 public static async Task < CursoredResponse < object ? > > ColumnDistinctValuesAsync < TEntity > (
@@ -208,10 +217,7 @@ public static async Task<PagedResponse<object>> ColumnDistinctValuesAsync<TEntit
208217 {
209218 // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract
210219 hasNull = await baseQuery . AnyAsync ( x => x == null , cancellationToken ) ;
211- if ( hasNull && take > 0 )
212- {
213- take -= 1 ;
214- }
220+ if ( hasNull && take > 0 ) take -= 1 ;
215221 }
216222
217223 var result = await baseQuery
@@ -221,38 +227,33 @@ public static async Task<PagedResponse<object>> ColumnDistinctValuesAsync<TEntit
221227 . ToListAsync ( cancellationToken ) ;
222228
223229 if ( ! filterEmpty || ! hasNull )
224- {
225230 return new CursoredResponse < object ? > ( result ! , model . PageSize ) ;
226- }
227231
228232 if ( result . Count > 0 && ReferenceEquals ( result [ ^ 1 ] , null ) )
229- {
230233 result . RemoveAt ( result . Count - 1 ) ;
231- }
232234
233235 result . Insert ( 0 , null ! ) ;
234236 return new CursoredResponse < object ? > ( result ! , model . PageSize ) ;
235237 }
236238
237- // Encrypted ( byte[]) path:
239+ // Encrypted path (scalar byte[] or IEnumerable<byte[]>)
238240 var encryptedQuery = query
239241 . ApplyFiltering ( gridifyModel , mapper )
240- . Select ( CreateSelector < TEntity > ( model . PropertyName ) ) ;
242+ . ApplySelect ( model . PropertyName , mapper ) ; // IQueryable<object?>
241243
242244 if ( string . IsNullOrWhiteSpace ( model . Filter ) )
243245 {
246+ // EF-translatable: only checks if the projection itself is NULL in DB
244247 // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract
245248 var hasNull = await encryptedQuery . AnyAsync ( x => x == null , cancellationToken ) ;
246249
247- if ( hasNull )
248- return new CursoredResponse < object ? > ( [ null ] ,
249- model . PageSize ) ;
250-
251- return new CursoredResponse < object ? > ( [ ] , model . PageSize ) ;
250+ return hasNull
251+ ? new CursoredResponse < object ? > ( [ null ] , model . PageSize )
252+ : new CursoredResponse < object ? > ( [ ] , model . PageSize ) ;
252253 }
253254
254- var item = await encryptedQuery . FirstOrDefaultAsync ( cancellationToken ) ;
255- if ( item is null )
255+ var selected = await encryptedQuery . FirstOrDefaultAsync ( cancellationToken ) ;
256+ if ( selected is null )
256257 {
257258 return new CursoredResponse < object ? > ( [ ] , model . PageSize ) ;
258259 }
@@ -262,13 +263,19 @@ public static async Task<PagedResponse<object>> ColumnDistinctValuesAsync<TEntit
262263 throw new KeyNotFoundException ( "Decryptor is required for encrypted properties." ) ;
263264 }
264265
265- if ( item is not byte [ ] bytes )
266+ object ? decrypted = selected switch
266267 {
267- throw new InvalidCastException ( "Encrypted selector did not return a byte[] value." ) ;
268- }
268+ byte [ ] b => decryptor ( b ) ,
269+ IEnumerable < byte [ ] > bs => bs . FirstOrDefault ( ) is
270+ { } fb
271+ ? decryptor ( fb )
272+ : null ,
273+ _ => throw new InvalidCastException ( "Encrypted selector did not return a byte[] or IEnumerable<byte[]> value." )
274+ } ;
269275
270- var decrypted = decryptor ( bytes ) ;
271- return new CursoredResponse < object ? > ( [ decrypted ] , model . PageSize ) ;
276+ return decrypted is null
277+ ? new CursoredResponse < object ? > ( [ ] , model . PageSize )
278+ : new CursoredResponse < object ? > ( [ decrypted ] , model . PageSize ) ;
272279 }
273280
274281 // ---------- Aggregation ----------
0 commit comments