Faster languages
This commit is contained in:
@@ -156,7 +156,7 @@ namespace Umbraco.Core.Cache
|
||||
}
|
||||
|
||||
// does NOT clone anything, so be nice with the returned values
|
||||
private IEnumerable<TEntity> GetAllCached(Func<TId[], IEnumerable<TEntity>> performGetAll)
|
||||
internal IEnumerable<TEntity> GetAllCached(Func<TId[], IEnumerable<TEntity>> performGetAll)
|
||||
{
|
||||
// try the cache first
|
||||
var all = Cache.GetCacheItem<DeepCloneableList<TEntity>>(GetEntityTypeCacheKey());
|
||||
|
||||
@@ -6,5 +6,8 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
ILanguage GetByCultureName(string cultureName);
|
||||
ILanguage GetByIsoCode(string isoCode);
|
||||
|
||||
int GetIdByIsoCode(string isoCode);
|
||||
string GetIsoCodeById(int id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,21 +18,24 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
|
||||
/// </summary>
|
||||
internal class LanguageRepository : NPocoRepositoryBase<int, ILanguage>, ILanguageRepository
|
||||
{
|
||||
private readonly Dictionary<string, int> _codeIdMap = new Dictionary<string, int>();
|
||||
private readonly Dictionary<int, string> _idCodeMap = new Dictionary<int, string>();
|
||||
private FullDataSetRepositoryCachePolicy<ILanguage, int> _cachePolicy;
|
||||
|
||||
public LanguageRepository(IScopeAccessor scopeAccessor, CacheHelper cache, ILogger logger)
|
||||
: base(scopeAccessor, cache, logger)
|
||||
{ }
|
||||
|
||||
protected override IRepositoryCachePolicy<ILanguage, int> CreateCachePolicy()
|
||||
{
|
||||
return new FullDataSetRepositoryCachePolicy<ILanguage, int>(GlobalIsolatedCache, ScopeAccessor, GetEntityId, /*expires:*/ false);
|
||||
return _cachePolicy = new FullDataSetRepositoryCachePolicy<ILanguage, int>(GlobalIsolatedCache, ScopeAccessor, GetEntityId, /*expires:*/ false);
|
||||
}
|
||||
|
||||
#region Overrides of RepositoryBase<int,Language>
|
||||
|
||||
protected override ILanguage PerformGet(int id)
|
||||
{
|
||||
//use the underlying GetAll which will force cache all domains
|
||||
return GetMany().FirstOrDefault(x => x.Id == id);
|
||||
throw new NotSupportedException(); // not required since policy is full dataset
|
||||
}
|
||||
|
||||
protected override IEnumerable<ILanguage> PerformGetAll(params int[] ids)
|
||||
@@ -47,8 +50,22 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
|
||||
//even though legacy didn't sort, it should be by id
|
||||
sql.OrderBy<LanguageDto>(dto => dto.Id);
|
||||
|
||||
// get languages
|
||||
var languages = Database.Fetch<LanguageDto>(sql).Select(ConvertFromDto).ToList();
|
||||
|
||||
return Database.Fetch<LanguageDto>(sql).Select(ConvertFromDto);
|
||||
// initialize the code-id map
|
||||
lock (_codeIdMap)
|
||||
{
|
||||
_codeIdMap.Clear();
|
||||
_idCodeMap.Clear();
|
||||
foreach (var language in languages)
|
||||
{
|
||||
_codeIdMap[language.IsoCode] = language.Id;
|
||||
_idCodeMap[language.Id] = language.IsoCode;
|
||||
}
|
||||
}
|
||||
|
||||
return languages;
|
||||
}
|
||||
|
||||
protected override IEnumerable<ILanguage> PerformGetByQuery(IQuery<ILanguage> query)
|
||||
@@ -184,14 +201,40 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
|
||||
|
||||
public ILanguage GetByCultureName(string cultureName)
|
||||
{
|
||||
//use the underlying GetAll which will force cache all languages
|
||||
// use the underlying GetMany which will force cache all languages
|
||||
// TODO we are cloning ALL in GetMany just to retrieve ONE, this is surely not optimized
|
||||
return GetMany().FirstOrDefault(x => x.CultureName.InvariantEquals(cultureName));
|
||||
}
|
||||
|
||||
public ILanguage GetByIsoCode(string isoCode)
|
||||
{
|
||||
//use the underlying GetAll which will force cache all languages
|
||||
return GetMany().FirstOrDefault(x => x.IsoCode.InvariantEquals(isoCode));
|
||||
_cachePolicy.GetAllCached(PerformGetAll); // ensure cache is populated, in a non-expensive way
|
||||
var id = GetIdByIsoCode(isoCode);
|
||||
return Get(id);
|
||||
}
|
||||
|
||||
// fast way of getting an id for an isoCode - avoiding cloning
|
||||
// _codeIdMap is rebuilt whenever PerformGetAll runs
|
||||
public int GetIdByIsoCode(string isoCode)
|
||||
{
|
||||
_cachePolicy.GetAllCached(PerformGetAll); // ensure cache is populated, in a non-expensive way
|
||||
lock (_codeIdMap)
|
||||
{
|
||||
if (_codeIdMap.TryGetValue(isoCode, out var id)) return id;
|
||||
}
|
||||
throw new ArgumentException($"Code {isoCode} does not correspond to an existing language.", nameof(isoCode));
|
||||
}
|
||||
|
||||
// fast way of getting an isoCode for an id - avoiding cloning
|
||||
// _idCodeMap is rebuilt whenever PerformGetAll runs
|
||||
public string GetIsoCodeById(int id)
|
||||
{
|
||||
_cachePolicy.GetAllCached(PerformGetAll); // ensure cache is populated, in a non-expensive way
|
||||
lock (_codeIdMap) // yes, we want to lock _codeIdMap
|
||||
{
|
||||
if (_idCodeMap.TryGetValue(id, out var isoCode)) return isoCode;
|
||||
}
|
||||
throw new ArgumentException($"Id {id} does not correspond to an existing language.", nameof(id),);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,6 +117,11 @@ namespace Umbraco.Core.Services
|
||||
/// <returns><see cref="Language"/></returns>
|
||||
ILanguage GetLanguageByIsoCode(string isoCode);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a language identifier by its iso code.
|
||||
/// </summary>
|
||||
int GetLanguageIdByIsoCode(string isoCode);
|
||||
|
||||
/// <summary>
|
||||
/// Gets all available languages
|
||||
/// </summary>
|
||||
|
||||
@@ -316,6 +316,15 @@ namespace Umbraco.Core.Services.Implement
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public int GetLanguageIdByIsoCode(string isoCode)
|
||||
{
|
||||
using (ScopeProvider.CreateScope(autoComplete: true))
|
||||
{
|
||||
return _languageRepository.GetIdByIsoCode(isoCode);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all available languages
|
||||
/// </summary>
|
||||
|
||||
Reference in New Issue
Block a user