diff --git a/src/BUTR.Site.NexusMods.Server.ValueObjects.Vogen/BUTR.Site.NexusMods.Server.ValueObjects.Vogen.csproj b/src/BUTR.Site.NexusMods.Server.ValueObjects.Vogen/BUTR.Site.NexusMods.Server.ValueObjects.Vogen.csproj
index 474e6ffc..dacdc498 100644
--- a/src/BUTR.Site.NexusMods.Server.ValueObjects.Vogen/BUTR.Site.NexusMods.Server.ValueObjects.Vogen.csproj
+++ b/src/BUTR.Site.NexusMods.Server.ValueObjects.Vogen/BUTR.Site.NexusMods.Server.ValueObjects.Vogen.csproj
@@ -12,7 +12,7 @@
-
+
diff --git a/src/BUTR.Site.NexusMods.Server/BUTR.Site.NexusMods.Server.csproj b/src/BUTR.Site.NexusMods.Server/BUTR.Site.NexusMods.Server.csproj
index a176a5d8..8c80d1aa 100644
--- a/src/BUTR.Site.NexusMods.Server/BUTR.Site.NexusMods.Server.csproj
+++ b/src/BUTR.Site.NexusMods.Server/BUTR.Site.NexusMods.Server.csproj
@@ -17,35 +17,35 @@
-
+
-
+
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
-
-
+
+
-
+
-
+
@@ -53,10 +53,10 @@
-
+
-
-
+
+
diff --git a/src/BUTR.Site.NexusMods.Server/Controllers/ExposedModsController.cs b/src/BUTR.Site.NexusMods.Server/Controllers/ExposedModsController.cs
index 715f0d0b..c2d7fca9 100644
--- a/src/BUTR.Site.NexusMods.Server/Controllers/ExposedModsController.cs
+++ b/src/BUTR.Site.NexusMods.Server/Controllers/ExposedModsController.cs
@@ -30,7 +30,7 @@ public ExposedModsController(ILogger logger, IUnitOfWorkF
[HttpPost("Paginated")]
public async Task?>> GetPaginatedAsync([FromBody, Required] PaginatedQuery query, CancellationToken ct)
{
- await using var unitOfRead = _unitOfWorkFactory.CreateUnitOfRead(TenantId.None);
+ await using var unitOfRead = _unitOfWorkFactory.CreateUnitOfRead();
var paginated = await unitOfRead.NexusModsModModules.GetExposedPaginatedAsync(query, ct);
@@ -40,7 +40,7 @@ public ExposedModsController(ILogger logger, IUnitOfWorkF
[HttpGet("Autocomplete/ModuleIds")]
public async Task?>> GetAutocompleteModuleIdsAsync([FromQuery, Required] ModuleId moduleId)
{
- await using var unitOfRead = _unitOfWorkFactory.CreateUnitOfRead(TenantId.None);
+ await using var unitOfRead = _unitOfWorkFactory.CreateUnitOfRead();
var moduleIds = await unitOfRead.Autocompletes.AutocompleteStartsWithAsync(x => x.Module.ModuleId, moduleId, CancellationToken.None);
diff --git a/src/BUTR.Site.NexusMods.Server/Extensions/QueryableExtensions.cs b/src/BUTR.Site.NexusMods.Server/Extensions/QueryableExtensions.cs
index b5c15efd..1e291a83 100644
--- a/src/BUTR.Site.NexusMods.Server/Extensions/QueryableExtensions.cs
+++ b/src/BUTR.Site.NexusMods.Server/Extensions/QueryableExtensions.cs
@@ -74,6 +74,7 @@ public static async Task> PaginatedAsync(this IQueryabl
where TEntity : class
{
var startTime = Stopwatch.GetTimestamp();
+
var count = await queryable.CountAsync(ct);
return new()
@@ -89,6 +90,49 @@ public static async Task> PaginatedAsync(this IQueryabl
}
};
}
+
+ public static Task> PaginatedGroupedAsync(this IQueryable queryable, PaginatedQuery query, uint maxPageSize = 20, Sorting? defaultSorting = default, CancellationToken ct = default)
+ where TEntity : class
+ {
+ var page = query.Page;
+ var pageSize = Math.Max(Math.Min(query.PageSize, maxPageSize), 5);
+ var filters = query.Filters ?? Enumerable.Empty();
+ var sortings = query.Sortings is null || query.Sortings.Count == 0
+ ? defaultSorting == null ? Array.Empty() : new List { defaultSorting }
+ : query.Sortings;
+
+ return queryable
+ .WithFilter(filters)
+ .WithSort(sortings)
+ .PaginatedGroupedAsync(page, pageSize, ct);
+ }
+
+ public static async Task> PaginatedGroupedAsync(this IQueryable queryable, uint page, uint pageSize, CancellationToken ct = default)
+ where TEntity : class
+ {
+ var startTime = Stopwatch.GetTimestamp();
+
+ var response = await queryable.GroupBy(_ => 1)
+ .Select(x => new
+ {
+ PageItems = x.Skip((int) ((page - 1) * pageSize)).Take((int) pageSize).ToList(),
+ Total = x.Count()
+ })
+ .FirstAsync(cancellationToken: ct);
+
+ return new()
+ {
+ StartTime = startTime,
+ Items = response.PageItems.ToAsyncEnumerable(),
+ Metadata = new()
+ {
+ PageSize = pageSize,
+ CurrentPage = page,
+ TotalCount = (uint) response.Total,
+ TotalPages = (uint) Math.Floor((double) response.Total / (double) pageSize),
+ }
+ };
+ }
public static Task> ToImmutableArrayAsync(this IQueryable source, CancellationToken ct = default)
{
diff --git a/src/BUTR.Site.NexusMods.Server/Repositories/CrashReportEntityRepository.cs b/src/BUTR.Site.NexusMods.Server/Repositories/CrashReportEntityRepository.cs
index 3f221068..d795dcb0 100644
--- a/src/BUTR.Site.NexusMods.Server/Repositories/CrashReportEntityRepository.cs
+++ b/src/BUTR.Site.NexusMods.Server/Repositories/CrashReportEntityRepository.cs
@@ -104,6 +104,6 @@ IQueryable DbQueryBase(Expression moduleIds.Contains(y.Module.ModuleId)) ||
x.ModuleInfos.Where(y => y.NexusModsMod != null).Any(y => nexusModsModIds.Contains(y.NexusModsMod!.NexusModsModId)));
- return await dbQuery.PaginatedAsync(query.Page, query.PageSize, ct);
+ return await dbQuery.PaginatedGroupedAsync(query.Page, query.PageSize, ct);
}
}
\ No newline at end of file
diff --git a/src/BUTR.Site.NexusMods.Server/Repositories/IRepository.cs b/src/BUTR.Site.NexusMods.Server/Repositories/IRepository.cs
index 29c56a78..46c47b23 100644
--- a/src/BUTR.Site.NexusMods.Server/Repositories/IRepository.cs
+++ b/src/BUTR.Site.NexusMods.Server/Repositories/IRepository.cs
@@ -129,12 +129,12 @@ public async Task> GetAllAsync(Expression> PaginatedAsync(PaginatedQuery query, uint maxPageSize = 20, Sorting? defaultSorting = default, CancellationToken ct = default) => InternalQuery
- .PaginatedAsync(query, maxPageSize, defaultSorting, ct);
+ .PaginatedGroupedAsync(query, maxPageSize, defaultSorting, ct);
public Task> PaginatedAsync(Expression> projection, PaginatedQuery query, uint maxPageSize = 20, Sorting? defaultSorting = default, CancellationToken ct = default)
where TProjection : class => InternalQuery
.Select(projection)
- .PaginatedAsync(query, maxPageSize, defaultSorting, ct);
+ .PaginatedGroupedAsync(query, maxPageSize, defaultSorting, ct);
public virtual void Add(TEntity entity) => _dbContext.Set()
diff --git a/src/BUTR.Site.NexusMods.Server/Repositories/NexusModsModToModuleEntityRepository.cs b/src/BUTR.Site.NexusMods.Server/Repositories/NexusModsModToModuleEntityRepository.cs
index 06022988..3664eeb5 100644
--- a/src/BUTR.Site.NexusMods.Server/Repositories/NexusModsModToModuleEntityRepository.cs
+++ b/src/BUTR.Site.NexusMods.Server/Repositories/NexusModsModToModuleEntityRepository.cs
@@ -57,10 +57,10 @@ public NexusModsModToModuleEntityRepository(IAppDbContextProvider appDbContextPr
public async Task> GetByStaffPaginatedAsync(PaginatedQuery query, CancellationToken ct) => await _dbContext.NexusModsModModules
.Where(x => x.LinkType == NexusModsModToModuleLinkType.ByStaff)
- .GroupBy(x => x.Module.ModuleId)
+ .GroupBy(x => new { x.Module.ModuleId })
.Select(x => new LinkedByStaffModuleNexusModsModsModel
{
- ModuleId = x.Key,
+ ModuleId = x.Key.ModuleId,
NexusModsMods = x.Select(y => new LinkedByStaffNexusModsModModel
{
NexusModsModId = y.NexusModsMod.NexusModsModId,
@@ -71,10 +71,10 @@ public async Task> GetByStaffPagin
public async Task> GetExposedPaginatedAsync(PaginatedQuery query, CancellationToken ct) => await _dbContext.NexusModsModModules
.Where(x => x.LinkType == NexusModsModToModuleLinkType.ByUnverifiedFileExposure)
- .GroupBy(x => x.NexusModsMod.NexusModsModId)
+ .GroupBy(x => new { x.NexusModsMod.NexusModsModId })
.Select(x => new LinkedByExposureNexusModsModModelsModel
{
- NexusModsModId = x.Key,
+ NexusModsModId = x.Key.NexusModsModId,
Modules = x.Select(y => new LinkedByExposureModuleModel
{
ModuleId = y.Module.ModuleId,
diff --git a/src/BUTR.Site.NexusMods.Server/Repositories/NexusModsUserRepository.cs b/src/BUTR.Site.NexusMods.Server/Repositories/NexusModsUserRepository.cs
index ada0cd56..0a3e3201 100644
--- a/src/BUTR.Site.NexusMods.Server/Repositories/NexusModsUserRepository.cs
+++ b/src/BUTR.Site.NexusMods.Server/Repositories/NexusModsUserRepository.cs
@@ -124,7 +124,7 @@ public async Task> GetNexusModsModsPaginatedAsync(Nex
});
return await availableModsByNexusModsModLinkage
- .PaginatedAsync(query, 20, new() { Property = nameof(UserLinkedModModel.NexusModsModId), Type = SortingType.Ascending }, ct);
+ .PaginatedGroupedAsync(query, 20, new() { Property = nameof(UserLinkedModModel.NexusModsModId), Type = SortingType.Ascending }, ct);
}
public async Task> GetAvailableModsPaginatedAsync(NexusModsUserId userId, PaginatedQuery query, CancellationToken ct)