Refactoring DatabaseCacheRepository to de-duplicate code and remove warnings (#19942)
* Refactoring to de-duplicate code and remove warnings. * Update src/Umbraco.PublishedCache.HybridCache/Persistence/DatabaseCacheRepository.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -21,6 +21,7 @@ using static Umbraco.Cms.Core.Persistence.SqlExtensionsStatics;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.HybridCache.Persistence;
|
||||
|
||||
/// <inheritdoc/>
|
||||
internal sealed class DatabaseCacheRepository : RepositoryBase, IDatabaseCacheRepository
|
||||
{
|
||||
private readonly IContentCacheDataSerializerFactory _contentCacheDataSerializerFactory;
|
||||
@@ -58,9 +59,11 @@ internal sealed class DatabaseCacheRepository : RepositoryBase, IDatabaseCacheRe
|
||||
_nucacheSettings = nucacheSettings;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task DeleteContentItemAsync(int id)
|
||||
=> await Database.ExecuteAsync("DELETE FROM cmsContentNu WHERE nodeId=@id", new { id = id });
|
||||
=> await Database.ExecuteAsync("DELETE FROM cmsContentNu WHERE nodeId = @id", new { id });
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task RefreshContentAsync(ContentCacheNode contentCacheNode, PublishedState publishedState)
|
||||
{
|
||||
IContentCacheDataSerializer serializer = _contentCacheDataSerializerFactory.Create(ContentCacheDataSerializerEntityType.Document);
|
||||
@@ -69,7 +72,8 @@ internal sealed class DatabaseCacheRepository : RepositoryBase, IDatabaseCacheRe
|
||||
if (contentCacheNode.IsDraft)
|
||||
{
|
||||
await OnRepositoryRefreshed(serializer, contentCacheNode, true);
|
||||
// if it's a draft node we don't need to worry about the published state
|
||||
|
||||
// If it's a draft node we don't need to worry about the published state.
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -84,6 +88,7 @@ internal sealed class DatabaseCacheRepository : RepositoryBase, IDatabaseCacheRe
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task RefreshMediaAsync(ContentCacheNode contentCacheNode)
|
||||
{
|
||||
IContentCacheDataSerializer serializer = _contentCacheDataSerializerFactory.Create(ContentCacheDataSerializerEntityType.Media);
|
||||
@@ -106,6 +111,16 @@ internal sealed class DatabaseCacheRepository : RepositoryBase, IDatabaseCacheRe
|
||||
if (contentTypeIds is not null && contentTypeIds.Count == 0 &&
|
||||
mediaTypeIds is not null && mediaTypeIds.Count == 0 &&
|
||||
memberTypeIds is not null && memberTypeIds.Count == 0)
|
||||
{
|
||||
TruncateContent();
|
||||
}
|
||||
|
||||
RebuildContentDbCache(serializer, _nucacheSettings.Value.SqlPageSize, contentTypeIds);
|
||||
RebuildMediaDbCache(serializer, _nucacheSettings.Value.SqlPageSize, mediaTypeIds);
|
||||
RebuildMemberDbCache(serializer, _nucacheSettings.Value.SqlPageSize, memberTypeIds);
|
||||
}
|
||||
|
||||
private void TruncateContent()
|
||||
{
|
||||
if (Database.DatabaseType == DatabaseType.SqlServer2012)
|
||||
{
|
||||
@@ -118,11 +133,7 @@ internal sealed class DatabaseCacheRepository : RepositoryBase, IDatabaseCacheRe
|
||||
}
|
||||
}
|
||||
|
||||
RebuildContentDbCache(serializer, _nucacheSettings.Value.SqlPageSize, contentTypeIds);
|
||||
RebuildMediaDbCache(serializer, _nucacheSettings.Value.SqlPageSize, mediaTypeIds);
|
||||
RebuildMemberDbCache(serializer, _nucacheSettings.Value.SqlPageSize, memberTypeIds);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task<ContentCacheNode?> GetContentSourceAsync(Guid key, bool preview = false)
|
||||
{
|
||||
Sql<ISqlContext>? sql = SqlContentSourcesSelect()
|
||||
@@ -147,6 +158,7 @@ internal sealed class DatabaseCacheRepository : RepositoryBase, IDatabaseCacheRe
|
||||
return CreateContentNodeKit(dto, serializer, preview);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task<IEnumerable<ContentCacheNode>> GetContentSourcesAsync(IEnumerable<Guid> keys, bool preview = false)
|
||||
{
|
||||
Sql<ISqlContext>? sql = SqlContentSourcesSelect()
|
||||
@@ -170,7 +182,7 @@ internal sealed class DatabaseCacheRepository : RepositoryBase, IDatabaseCacheRe
|
||||
private IEnumerable<ContentSourceDto> GetContentSourceByDocumentTypeKey(IEnumerable<Guid> documentTypeKeys, Guid objectType)
|
||||
{
|
||||
Guid[] keys = documentTypeKeys.ToArray();
|
||||
if (keys.Any() is false)
|
||||
if (keys.Length == 0)
|
||||
{
|
||||
return [];
|
||||
}
|
||||
@@ -190,6 +202,7 @@ internal sealed class DatabaseCacheRepository : RepositoryBase, IDatabaseCacheRe
|
||||
return GetContentNodeDtos(sql);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IEnumerable<ContentCacheNode> GetContentByContentTypeKey(IEnumerable<Guid> keys, ContentCacheDataSerializerEntityType entityType)
|
||||
{
|
||||
Guid objectType = entityType switch
|
||||
@@ -222,6 +235,7 @@ internal sealed class DatabaseCacheRepository : RepositoryBase, IDatabaseCacheRe
|
||||
public IEnumerable<Guid> GetDocumentKeysByContentTypeKeys(IEnumerable<Guid> keys, bool published = false)
|
||||
=> GetContentSourceByDocumentTypeKey(keys, Constants.ObjectTypes.Document).Where(x => x.Published == published).Select(x => x.Key);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task<ContentCacheNode?> GetMediaSourceAsync(Guid key)
|
||||
{
|
||||
Sql<ISqlContext>? sql = SqlMediaSourcesSelect()
|
||||
@@ -241,6 +255,7 @@ internal sealed class DatabaseCacheRepository : RepositoryBase, IDatabaseCacheRe
|
||||
return CreateMediaNodeKit(dto, serializer);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task<IEnumerable<ContentCacheNode>> GetMediaSourcesAsync(IEnumerable<Guid> keys)
|
||||
{
|
||||
Sql<ISqlContext>? sql = SqlMediaSourcesSelect()
|
||||
@@ -262,8 +277,7 @@ internal sealed class DatabaseCacheRepository : RepositoryBase, IDatabaseCacheRe
|
||||
|
||||
private async Task OnRepositoryRefreshed(IContentCacheDataSerializer serializer, ContentCacheNode content, bool preview)
|
||||
{
|
||||
// use a custom SQL to update row version on each update
|
||||
// db.InsertOrUpdate(dto);
|
||||
|
||||
ContentNuDto dto = GetDtoFromCacheNode(content, !preview, serializer);
|
||||
|
||||
await Database.InsertOrUpdateAsync(
|
||||
@@ -278,7 +292,12 @@ internal sealed class DatabaseCacheRepository : RepositoryBase, IDatabaseCacheRe
|
||||
});
|
||||
}
|
||||
|
||||
// assumes content tree lock
|
||||
/// <summary>
|
||||
/// Rebuilds the content database cache for documents.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Assumes content tree lock.
|
||||
/// </remarks>
|
||||
private void RebuildContentDbCache(IContentCacheDataSerializer serializer, int groupSize, IReadOnlyCollection<int>? contentTypeIds)
|
||||
{
|
||||
if (contentTypeIds is null)
|
||||
@@ -288,55 +307,35 @@ internal sealed class DatabaseCacheRepository : RepositoryBase, IDatabaseCacheRe
|
||||
|
||||
Guid contentObjectType = Constants.ObjectTypes.Document;
|
||||
|
||||
// remove all - if anything fails the transaction will rollback
|
||||
// Remove all - if anything fails the transaction will rollback.
|
||||
if (contentTypeIds.Count == 0)
|
||||
{
|
||||
// must support SQL-CE
|
||||
Database.Execute(
|
||||
@"DELETE FROM cmsContentNu
|
||||
WHERE cmsContentNu.nodeId IN (
|
||||
SELECT id FROM umbracoNode WHERE umbracoNode.nodeObjectType=@objType
|
||||
)",
|
||||
new { objType = contentObjectType });
|
||||
DeleteForObjectType(contentObjectType);
|
||||
}
|
||||
else
|
||||
{
|
||||
// assume number of ctypes won't blow IN(...)
|
||||
// must support SQL-CE
|
||||
Database.Execute(
|
||||
$@"DELETE FROM cmsContentNu
|
||||
WHERE cmsContentNu.nodeId IN (
|
||||
SELECT id FROM umbracoNode
|
||||
JOIN {Constants.DatabaseSchema.Tables.Content} ON {Constants.DatabaseSchema.Tables.Content}.nodeId=umbracoNode.id
|
||||
WHERE umbracoNode.nodeObjectType=@objType
|
||||
AND {Constants.DatabaseSchema.Tables.Content}.contentTypeId IN (@ctypes)
|
||||
)",
|
||||
new { objType = contentObjectType, ctypes = contentTypeIds });
|
||||
DeleteForObjectTypeAndContentTypes(contentObjectType, contentTypeIds);
|
||||
}
|
||||
|
||||
// insert back - if anything fails the transaction will rollback
|
||||
IQuery<IContent> query = SqlContext.Query<IContent>();
|
||||
if (contentTypeIds.Count > 0)
|
||||
{
|
||||
query = query.WhereIn(x => x.ContentTypeId, contentTypeIds); // assume number of ctypes won't blow IN(...)
|
||||
}
|
||||
// Insert back - if anything fails the transaction will rollback.
|
||||
IQuery<IContent> query = GetInsertQuery<IContent>(contentTypeIds);
|
||||
|
||||
long pageIndex = 0;
|
||||
long processed = 0;
|
||||
long total;
|
||||
do
|
||||
{
|
||||
// the tree is locked, counting and comparing to total is safe
|
||||
// The tree is locked, counting and comparing to total is safe.
|
||||
IEnumerable<IContent> descendants =
|
||||
_documentRepository.GetPage(query, pageIndex++, groupSize, out total, null, Ordering.By("Path"));
|
||||
var items = new List<ContentNuDto>();
|
||||
var count = 0;
|
||||
foreach (IContent c in descendants)
|
||||
{
|
||||
// always the edited version
|
||||
// Always include the edited version.
|
||||
items.Add(GetDtoFromContent(c, false, serializer));
|
||||
|
||||
// and also the published version if it makes any sense
|
||||
// And also the published version if the document is published.
|
||||
if (c.Published)
|
||||
{
|
||||
items.Add(GetDtoFromContent(c, true, serializer));
|
||||
@@ -347,10 +346,16 @@ WHERE cmsContentNu.nodeId IN (
|
||||
|
||||
Database.BulkInsertRecords(items);
|
||||
processed += count;
|
||||
} while (processed < total);
|
||||
}
|
||||
while (processed < total);
|
||||
}
|
||||
|
||||
// assumes media tree lock
|
||||
/// <summary>
|
||||
/// Rebuilds the content database cache for media.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Assumes media tree lock.
|
||||
/// </remarks>
|
||||
private void RebuildMediaDbCache(IContentCacheDataSerializer serializer, int groupSize, IReadOnlyCollection<int>? contentTypeIds)
|
||||
{
|
||||
if (contentTypeIds is null)
|
||||
@@ -360,54 +365,40 @@ WHERE cmsContentNu.nodeId IN (
|
||||
|
||||
Guid mediaObjectType = Constants.ObjectTypes.Media;
|
||||
|
||||
// remove all - if anything fails the transaction will rollback
|
||||
// Remove all - if anything fails the transaction will rollback.
|
||||
if (contentTypeIds.Count == 0)
|
||||
{
|
||||
// must support SQL-CE
|
||||
Database.Execute(
|
||||
@"DELETE FROM cmsContentNu
|
||||
WHERE cmsContentNu.nodeId IN (
|
||||
SELECT id FROM umbracoNode WHERE umbracoNode.nodeObjectType=@objType
|
||||
)",
|
||||
new { objType = mediaObjectType });
|
||||
DeleteForObjectType(mediaObjectType);
|
||||
}
|
||||
else
|
||||
{
|
||||
// assume number of ctypes won't blow IN(...)
|
||||
// must support SQL-CE
|
||||
Database.Execute(
|
||||
$@"DELETE FROM cmsContentNu
|
||||
WHERE cmsContentNu.nodeId IN (
|
||||
SELECT id FROM umbracoNode
|
||||
JOIN {Constants.DatabaseSchema.Tables.Content} ON {Constants.DatabaseSchema.Tables.Content}.nodeId=umbracoNode.id
|
||||
WHERE umbracoNode.nodeObjectType=@objType
|
||||
AND {Constants.DatabaseSchema.Tables.Content}.contentTypeId IN (@ctypes)
|
||||
)",
|
||||
new { objType = mediaObjectType, ctypes = contentTypeIds });
|
||||
DeleteForObjectTypeAndContentTypes(mediaObjectType, contentTypeIds);
|
||||
}
|
||||
|
||||
// insert back - if anything fails the transaction will rollback
|
||||
IQuery<IMedia> query = SqlContext.Query<IMedia>();
|
||||
if (contentTypeIds.Count > 0)
|
||||
{
|
||||
query = query.WhereIn(x => x.ContentTypeId, contentTypeIds); // assume number of ctypes won't blow IN(...)
|
||||
}
|
||||
// Insert back - if anything fails the transaction will rollback.
|
||||
IQuery<IMedia> query = GetInsertQuery<IMedia>(contentTypeIds);
|
||||
|
||||
long pageIndex = 0;
|
||||
long processed = 0;
|
||||
long total;
|
||||
do
|
||||
{
|
||||
// the tree is locked, counting and comparing to total is safe
|
||||
// The tree is locked, counting and comparing to total is safe.
|
||||
IEnumerable<IMedia> descendants =
|
||||
_mediaRepository.GetPage(query, pageIndex++, groupSize, out total, null, Ordering.By("Path"));
|
||||
var items = descendants.Select(m => GetDtoFromContent(m, false, serializer)).ToArray();
|
||||
ContentNuDto[] items = descendants.Select(m => GetDtoFromContent(m, false, serializer)).ToArray();
|
||||
Database.BulkInsertRecords(items);
|
||||
processed += items.Length;
|
||||
} while (processed < total);
|
||||
}
|
||||
while (processed < total);
|
||||
}
|
||||
|
||||
// assumes member tree lock
|
||||
/// <summary>
|
||||
/// Rebuilds the content database cache for members.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Assumes member tree lock.
|
||||
/// </remarks>
|
||||
private void RebuildMemberDbCache(IContentCacheDataSerializer serializer, int groupSize, IReadOnlyCollection<int>? contentTypeIds)
|
||||
{
|
||||
if (contentTypeIds is null)
|
||||
@@ -417,38 +408,18 @@ WHERE cmsContentNu.nodeId IN (
|
||||
|
||||
Guid memberObjectType = Constants.ObjectTypes.Member;
|
||||
|
||||
// remove all - if anything fails the transaction will rollback
|
||||
// Remove all - if anything fails the transaction will rollback.
|
||||
if (contentTypeIds.Count == 0)
|
||||
{
|
||||
// must support SQL-CE
|
||||
Database.Execute(
|
||||
@"DELETE FROM cmsContentNu
|
||||
WHERE cmsContentNu.nodeId IN (
|
||||
SELECT id FROM umbracoNode WHERE umbracoNode.nodeObjectType=@objType
|
||||
)",
|
||||
new { objType = memberObjectType });
|
||||
DeleteForObjectType(memberObjectType);
|
||||
}
|
||||
else
|
||||
{
|
||||
// assume number of ctypes won't blow IN(...)
|
||||
// must support SQL-CE
|
||||
Database.Execute(
|
||||
$@"DELETE FROM cmsContentNu
|
||||
WHERE cmsContentNu.nodeId IN (
|
||||
SELECT id FROM umbracoNode
|
||||
JOIN {Constants.DatabaseSchema.Tables.Content} ON {Constants.DatabaseSchema.Tables.Content}.nodeId=umbracoNode.id
|
||||
WHERE umbracoNode.nodeObjectType=@objType
|
||||
AND {Constants.DatabaseSchema.Tables.Content}.contentTypeId IN (@ctypes)
|
||||
)",
|
||||
new { objType = memberObjectType, ctypes = contentTypeIds });
|
||||
DeleteForObjectTypeAndContentTypes(memberObjectType, contentTypeIds);
|
||||
}
|
||||
|
||||
// insert back - if anything fails the transaction will rollback
|
||||
IQuery<IMember> query = SqlContext.Query<IMember>();
|
||||
if (contentTypeIds.Count > 0)
|
||||
{
|
||||
query = query.WhereIn(x => x.ContentTypeId, contentTypeIds); // assume number of ctypes won't blow IN(...)
|
||||
}
|
||||
// Insert back - if anything fails the transaction will rollback.
|
||||
IQuery<IMember> query = GetInsertQuery<IMember>(contentTypeIds);
|
||||
|
||||
long pageIndex = 0;
|
||||
long processed = 0;
|
||||
@@ -460,12 +431,46 @@ WHERE cmsContentNu.nodeId IN (
|
||||
ContentNuDto[] items = descendants.Select(m => GetDtoFromContent(m, false, serializer)).ToArray();
|
||||
Database.BulkInsertRecords(items);
|
||||
processed += items.Length;
|
||||
} while (processed < total);
|
||||
}
|
||||
while (processed < total);
|
||||
}
|
||||
|
||||
private void DeleteForObjectType(Guid nodeObjectType) =>
|
||||
Database.Execute(
|
||||
@"
|
||||
DELETE FROM cmsContentNu
|
||||
WHERE cmsContentNu.nodeId IN (
|
||||
SELECT id FROM umbracoNode WHERE umbracoNode.nodeObjectType = @objType
|
||||
)",
|
||||
new { objType = nodeObjectType });
|
||||
|
||||
private void DeleteForObjectTypeAndContentTypes(Guid nodeObjectType, IReadOnlyCollection<int> contentTypeIds) =>
|
||||
Database.Execute(
|
||||
$@"
|
||||
DELETE FROM cmsContentNu
|
||||
WHERE cmsContentNu.nodeId IN (
|
||||
SELECT id FROM umbracoNode
|
||||
JOIN {Constants.DatabaseSchema.Tables.Content} ON {Constants.DatabaseSchema.Tables.Content}.nodeId=umbracoNode.id
|
||||
WHERE umbracoNode.nodeObjectType = @objType
|
||||
AND {Constants.DatabaseSchema.Tables.Content}.contentTypeId IN (@ctypes)
|
||||
)",
|
||||
new { objType = nodeObjectType, ctypes = contentTypeIds });
|
||||
|
||||
private IQuery<TContent> GetInsertQuery<TContent>(IReadOnlyCollection<int> contentTypeIds)
|
||||
where TContent : IContentBase
|
||||
{
|
||||
IQuery<TContent> query = SqlContext.Query<TContent>();
|
||||
if (contentTypeIds.Count > 0)
|
||||
{
|
||||
query = query.WhereIn(x => x.ContentTypeId, contentTypeIds);
|
||||
}
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
private ContentNuDto GetDtoFromCacheNode(ContentCacheNode cacheNode, bool published, IContentCacheDataSerializer serializer)
|
||||
{
|
||||
// the dictionary that will be serialized
|
||||
// Prepare the data structure that will be serialized.
|
||||
var contentCacheData = new ContentCacheDataModel
|
||||
{
|
||||
PropertyData = cacheNode.Data?.Properties,
|
||||
@@ -487,23 +492,19 @@ WHERE cmsContentNu.nodeId IN (
|
||||
|
||||
private ContentNuDto GetDtoFromContent(IContentBase content, bool published, IContentCacheDataSerializer serializer)
|
||||
{
|
||||
// should inject these in ctor
|
||||
// BUT for the time being we decide not to support ConvertDbToXml/String
|
||||
// var propertyEditorResolver = PropertyEditorResolver.Current;
|
||||
// var dataTypeService = ApplicationContext.Current.Services.DataTypeService;
|
||||
var propertyData = new Dictionary<string, PropertyData[]>();
|
||||
foreach (IProperty prop in content.Properties)
|
||||
{
|
||||
var pdatas = new List<PropertyData>();
|
||||
foreach (IPropertyValue pvalue in prop.Values.OrderBy(x => x.Culture))
|
||||
{
|
||||
// sanitize - properties should be ok but ... never knows
|
||||
// Sanitize - properties should be ok but ... never knows.
|
||||
if (!prop.PropertyType.SupportsVariation(pvalue.Culture, pvalue.Segment))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// note: at service level, invariant is 'null', but here invariant becomes 'string.Empty'
|
||||
// Note: at service level, invariant is 'null', but here invariant becomes 'string.Empty'
|
||||
var value = published ? pvalue.PublishedValue : pvalue.EditedValue;
|
||||
if (value != null)
|
||||
{
|
||||
@@ -521,7 +522,7 @@ WHERE cmsContentNu.nodeId IN (
|
||||
|
||||
var cultureData = new Dictionary<string, CultureVariation>();
|
||||
|
||||
// sanitize - names should be ok but ... never knows
|
||||
// Sanitize - names should be ok but ... never knows.
|
||||
if (content.ContentType.VariesByCulture())
|
||||
{
|
||||
ContentCultureInfosCollection? infos = content is IContent document
|
||||
@@ -530,7 +531,6 @@ WHERE cmsContentNu.nodeId IN (
|
||||
: document.CultureInfos
|
||||
: content.CultureInfos;
|
||||
|
||||
// ReSharper disable once UseDeconstruction
|
||||
if (infos is not null)
|
||||
{
|
||||
foreach (ContentCultureInfos cultureInfo in infos)
|
||||
@@ -547,7 +547,7 @@ WHERE cmsContentNu.nodeId IN (
|
||||
}
|
||||
}
|
||||
|
||||
// the dictionary that will be serialized
|
||||
// Prepare the data structure that will be serialized.
|
||||
var contentCacheData = new ContentCacheDataModel
|
||||
{
|
||||
PropertyData = propertyData,
|
||||
@@ -566,7 +566,6 @@ WHERE cmsContentNu.nodeId IN (
|
||||
return dto;
|
||||
}
|
||||
|
||||
// we want arrays, we want them all loaded, not an enumerable
|
||||
private Sql<ISqlContext> SqlContentSourcesSelect(Func<ISqlContext, Sql<ISqlContext>>? joins = null)
|
||||
{
|
||||
SqlTemplate sqlTemplate = SqlContext.Templates.Get(
|
||||
@@ -632,36 +631,6 @@ WHERE cmsContentNu.nodeId IN (
|
||||
return sql;
|
||||
}
|
||||
|
||||
private Sql<ISqlContext> SqlContentSourcesSelectUmbracoNodeJoin(ISqlContext sqlContext)
|
||||
{
|
||||
ISqlSyntaxProvider syntax = sqlContext.SqlSyntax;
|
||||
|
||||
SqlTemplate sqlTemplate = sqlContext.Templates.Get(
|
||||
Constants.SqlTemplates.NuCacheDatabaseDataSource.SourcesSelectUmbracoNodeJoin, builder =>
|
||||
builder.InnerJoin<NodeDto>("x")
|
||||
.On<NodeDto, NodeDto>(
|
||||
(left, right) => left.NodeId == right.NodeId ||
|
||||
SqlText<bool>(left.Path, right.Path,
|
||||
(lp, rp) => $"({lp} LIKE {syntax.GetConcat(rp, "',%'")})"),
|
||||
aliasRight: "x"));
|
||||
|
||||
Sql<ISqlContext> sql = sqlTemplate.Sql();
|
||||
return sql;
|
||||
}
|
||||
|
||||
private Sql<ISqlContext> SqlWhereNodeId(ISqlContext sqlContext, int id)
|
||||
{
|
||||
ISqlSyntaxProvider syntax = sqlContext.SqlSyntax;
|
||||
|
||||
SqlTemplate sqlTemplate = sqlContext.Templates.Get(
|
||||
Constants.SqlTemplates.NuCacheDatabaseDataSource.WhereNodeId,
|
||||
builder =>
|
||||
builder.Where<NodeDto>(x => x.NodeId == SqlTemplate.Arg<int>("id")));
|
||||
|
||||
Sql<ISqlContext> sql = sqlTemplate.Sql(id);
|
||||
return sql;
|
||||
}
|
||||
|
||||
private Sql<ISqlContext> SqlWhereNodeKey(ISqlContext sqlContext, Guid key)
|
||||
{
|
||||
ISqlSyntaxProvider syntax = sqlContext.SqlSyntax;
|
||||
@@ -702,10 +671,8 @@ WHERE cmsContentNu.nodeId IN (
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a slightly more optimized query to use for the document counting when paging over the content sources
|
||||
/// Returns a slightly more optimized query to use for the document counting when paging over the content sources.
|
||||
/// </summary>
|
||||
/// <param name="joins"></param>
|
||||
/// <returns></returns>
|
||||
private Sql<ISqlContext> SqlContentSourcesCount(Func<ISqlContext, Sql<ISqlContext>>? joins = null)
|
||||
{
|
||||
SqlTemplate sqlTemplate = SqlContext.Templates.Get(
|
||||
|
||||
@@ -3,6 +3,9 @@ using Umbraco.Cms.Infrastructure.HybridCache.Serialization;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.HybridCache.Persistence;
|
||||
|
||||
/// <summary>
|
||||
/// Defines a repository for persisting content cache data.
|
||||
/// </summary>
|
||||
internal interface IDatabaseCacheRepository
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
Reference in New Issue
Block a user