fix: paginate PersonRepository.SearchQuery by ID before loading albums
Include + Skip/Take on a collection navigation can produce duplicate people when sorted by album count, because pagination operates on joined rows. Fix by selecting paged IDs first, then loading the full entities with Include for those IDs.
This commit is contained in:
@@ -59,7 +59,7 @@ public class PersonRepository(LactoseDbContext context) : IPersonRepository {
|
|||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public IEnumerable<Person> SearchQuery(string query, int page = 0, int pageSize = 30, string? sortBy = null, bool sortAsc = true, Guid userId = default, EAccessLevel accessLevel = EAccessLevel.User) {
|
public IEnumerable<Person> SearchQuery(string query, int page = 0, int pageSize = 30, string? sortBy = null, bool sortAsc = true, Guid userId = default, EAccessLevel accessLevel = EAccessLevel.User) {
|
||||||
IQueryable<Person> peopleQuery = context.People.Include(p => p.Albums);
|
IQueryable<Person> peopleQuery = context.People;
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(query))
|
if (!string.IsNullOrEmpty(query))
|
||||||
peopleQuery = peopleQuery.Where(p => EF.Functions.ILike(p.Name, $"%{query}%"));
|
peopleQuery = peopleQuery.Where(p => EF.Functions.ILike(p.Name, $"%{query}%"));
|
||||||
@@ -80,9 +80,19 @@ public class PersonRepository(LactoseDbContext context) : IPersonRepository {
|
|||||||
_ => sortAsc ? peopleQuery.OrderBy(p => p.Name) : peopleQuery.OrderByDescending(p => p.Name),
|
_ => sortAsc ? peopleQuery.OrderBy(p => p.Name) : peopleQuery.OrderByDescending(p => p.Name),
|
||||||
};
|
};
|
||||||
|
|
||||||
return ordered
|
var pagedIds = ordered
|
||||||
|
.Select(p => p.Id)
|
||||||
.Skip(page * pageSize)
|
.Skip(page * pageSize)
|
||||||
.Take(pageSize);
|
.Take(pageSize)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
var pagedPeople = context.People
|
||||||
|
.Include(p => p.Albums)
|
||||||
|
.Where(p => pagedIds.Contains(p.Id))
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
var idOrder = pagedIds.Select((id, i) => (id, i)).ToDictionary(x => x.id, x => x.i);
|
||||||
|
return [.. pagedPeople.OrderBy(p => idOrder.GetValueOrDefault(p.Id))];
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|||||||
Reference in New Issue
Block a user