Merge pull request #840 from nolt/fix-admin-panel-account-search
Search accounts in the database instead of loading all of them (cherry picked from commit 4e806cbe64f855a765e864c0c2ff45238f487e36)
This commit is contained in:
@@ -100,6 +100,26 @@ internal class PlayerContext : CachingEntityFrameworkContext, IPlayerContext
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async ValueTask<IEnumerable<DataModel.Entities.Account>> SearchAccountsAsync(string searchTerm, int skip, int count, CancellationToken cancellationToken = default)
|
||||
{
|
||||
using (this.RepositoryProvider.ContextStack.UseContext(this))
|
||||
{
|
||||
// Invariant: this one runs in .NET, so it must not depend on the server's locale - in a
|
||||
// Turkish one, "I".ToLower() is a dotless "ı" and the term would match nothing. The
|
||||
// ToLower() calls inside the query below are a different matter: they are translated to
|
||||
// the database's own lower(), which is why they cannot take a culture.
|
||||
var term = searchTerm.ToLowerInvariant();
|
||||
return await this.Context.Set<Account>().AsNoTracking()
|
||||
.Where(a => a.LoginName.ToLower().Contains(term)
|
||||
|| a.RawCharacters.Any(c => c.Name.ToLower().Contains(term)))
|
||||
.OrderBy(a => a.LoginName)
|
||||
.Skip(skip)
|
||||
.Take(count)
|
||||
.ToListAsync(cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async ValueTask<DataModel.Entities.Account?> GetAccountByCharacterNameAsync(string characterName, CancellationToken cancellationToken = default)
|
||||
{
|
||||
|
||||
@@ -78,6 +78,19 @@ public interface IPlayerContext : IContext
|
||||
/// </returns>
|
||||
ValueTask<IEnumerable<Account>> GetAccountsOrderedByLoginNameAsync(int skip, int count, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the accounts which contain the search term in their login name or in one of
|
||||
/// their character names, ordered by login name.
|
||||
/// </summary>
|
||||
/// <param name="searchTerm">The search term.</param>
|
||||
/// <param name="skip">The skip count.</param>
|
||||
/// <param name="count">The count.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>
|
||||
/// The account objects, without dependent data.
|
||||
/// </returns>
|
||||
ValueTask<IEnumerable<Account>> SearchAccountsAsync(string searchTerm, int skip, int count, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the account by character name.
|
||||
/// </summary>
|
||||
|
||||
@@ -57,6 +57,18 @@ public class PlayerInMemoryContext : InMemoryContext, IPlayerContext
|
||||
return allAccounts.OrderBy(a => a.LoginName).Skip(skip).Take(count);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async ValueTask<IEnumerable<MUnique.OpenMU.DataModel.Entities.Account>> SearchAccountsAsync(string searchTerm, int skip, int count, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var allAccounts = await this.Provider.GetRepository<Account>().GetAllAsync(cancellationToken).ConfigureAwait(false);
|
||||
return allAccounts
|
||||
.Where(a => a.LoginName.Contains(searchTerm, StringComparison.InvariantCultureIgnoreCase)
|
||||
|| a.Characters.Any(c => c.Name.Contains(searchTerm, StringComparison.InvariantCultureIgnoreCase)))
|
||||
.OrderBy(a => a.LoginName)
|
||||
.Skip(skip)
|
||||
.Take(count);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async ValueTask<bool> CanSaveLetterAsync(Interfaces.LetterHeader letterHeader, CancellationToken cancellationToken = default)
|
||||
{
|
||||
|
||||
@@ -80,18 +80,14 @@ public class AccountService : IDataService<Account>, ISupportDataChangedNotifica
|
||||
return (await playerContext.GetAccountsOrderedByLoginNameAsync(offset, count).ConfigureAwait(false)).ToList();
|
||||
}
|
||||
|
||||
var allAccounts = await playerContext.GetAsync<Account>().ConfigureAwait(false);
|
||||
var results = allAccounts.Where(account =>
|
||||
(account.LoginName != null && account.LoginName.Contains(filter, StringComparison.InvariantCultureIgnoreCase))
|
||||
|| account.Characters.Any(c => c.Name != null && c.Name.Contains(filter, StringComparison.InvariantCultureIgnoreCase))
|
||||
).ToList();
|
||||
|
||||
if (offset >= results.Count)
|
||||
var results = (await playerContext.SearchAccountsAsync(filter, offset, count).ConfigureAwait(false)).ToList();
|
||||
if (results.Count == 0 && offset > 0)
|
||||
{
|
||||
return results.Take(count).ToList();
|
||||
// The filter narrowed the result set down to less entries than the current page offset - show the first page instead.
|
||||
results = (await playerContext.SearchAccountsAsync(filter, 0, count).ConfigureAwait(false)).ToList();
|
||||
}
|
||||
|
||||
return results.Skip(offset).Take(count).ToList();
|
||||
return results;
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user