Skip to content

Commit e6be013

Browse files
authored
Merge pull request #54 from PandaTechAM/development
ColumnDistinctValue null handling extended
2 parents 76a6b8d + 9da6b70 commit e6be013

File tree

2 files changed

+65
-17
lines changed

2 files changed

+65
-17
lines changed

src/GridifyExtensions/Extensions/QueryableExtensions.cs

Lines changed: 63 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -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 ----------

src/GridifyExtensions/GridifyExtensions.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@
88
<PackageReadmeFile>Readme.md</PackageReadmeFile>
99
<Authors>Pandatech</Authors>
1010
<Copyright>MIT</Copyright>
11-
<Version>2.1.1</Version>
11+
<Version>2.1.2</Version>
1212
<PackageId>Pandatech.GridifyExtensions</PackageId>
1313
<Title>Pandatech.Gridify.Extensions</Title>
1414
<PackageTags>Pandatech, library, Gridify, Pagination, Filters</PackageTags>
1515
<Description>Pandatech.Gridify.Extensions simplifies and extends the functionality of the Gridify NuGet package. It provides additional extension methods and functionality to streamline data filtering and pagination, making it more intuitive and powerful to use in .NET applications. Our enhancements ensure more flexibility, reduce boilerplate code, and improve overall developer productivity when working with Gridify.</Description>
1616
<RepositoryUrl>https://github.com/PandaTechAM/be-lib-gridify-extensions</RepositoryUrl>
17-
<PackageReleaseNotes>TotalCount bug fix on edge cases</PackageReleaseNotes>
17+
<PackageReleaseNotes>ColumnDistinctValue null handling extended</PackageReleaseNotes>
1818
</PropertyGroup>
1919

2020
<ItemGroup>

0 commit comments

Comments
 (0)