From 0bb27b8ebd1aba7b54866d9075d2f1efe11f6c97 Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 10 Aug 2017 00:22:15 +1000 Subject: [PATCH 1/7] U4-10263 Missing UDI + GUID friendly MediaService.GetByIds, ContentService.GetByIds --- src/Umbraco.Core/Services/ContentService.cs | 20 ++++++++++++++++ .../Services/ContentServiceExtensions.cs | 24 ++++++++++++++++++- src/Umbraco.Core/Services/IContentService.cs | 16 +++++++++++++ src/Umbraco.Core/Services/IMediaService.cs | 16 +++++++++++++ src/Umbraco.Core/Services/MediaService.cs | 22 ++++++++++++++++- .../Services/MediaServiceExtensions.cs | 24 +++++++++++++++++++ src/Umbraco.Core/Umbraco.Core.csproj | 1 + 7 files changed, 121 insertions(+), 2 deletions(-) create mode 100644 src/Umbraco.Core/Services/MediaServiceExtensions.cs diff --git a/src/Umbraco.Core/Services/ContentService.cs b/src/Umbraco.Core/Services/ContentService.cs index 60788eb958..b635caef5b 100644 --- a/src/Umbraco.Core/Services/ContentService.cs +++ b/src/Umbraco.Core/Services/ContentService.cs @@ -143,6 +143,26 @@ namespace Umbraco.Core.Services } } + /// + /// Creates an object using the alias of the + /// that this Content should based on. + /// + /// + /// Note that using this method will simply return a new IContent without any identity + /// as it has not yet been persisted. It is intended as a shortcut to creating new content objects + /// that does not invoke a save operation against the database. + /// + /// Name of the Content object + /// Id of Parent for the new Content + /// Alias of the + /// Optional id of the user creating the content + /// + public IContent CreateContent(string name, Guid parentId, string contentTypeAlias, int userId = 0) + { + var parent = GetById(parentId); + return CreateContent(name, parent, contentTypeAlias, userId); + } + /// /// Creates an object using the alias of the /// that this Content should based on. diff --git a/src/Umbraco.Core/Services/ContentServiceExtensions.cs b/src/Umbraco.Core/Services/ContentServiceExtensions.cs index b3380cf1bf..d7f9c52d38 100644 --- a/src/Umbraco.Core/Services/ContentServiceExtensions.cs +++ b/src/Umbraco.Core/Services/ContentServiceExtensions.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using System.Linq; using Umbraco.Core.Models; @@ -8,8 +9,29 @@ using Umbraco.Core.Persistence.Repositories; namespace Umbraco.Core.Services { + /// + /// Content service extension methods + /// public static class ContentServiceExtensions - { + { + /// + /// Method to create an IContent object based on the Udi of a parent + /// + /// + /// + /// + /// + /// + /// + public static IContent CreateContent(this IContentService contentService, string name, Udi parentId, string mediaTypeAlias, int userId = 0) + { + var guidUdi = parentId as GuidUdi; + if (guidUdi == null) + throw new InvalidOperationException("The UDI provided isn't of type " + typeof(GuidUdi) + " which is required by content"); + var parent = contentService.GetById(guidUdi.Guid); + return contentService.CreateContent(name, parent, mediaTypeAlias, userId); + } + /// /// Remove all permissions for this user for all nodes /// diff --git a/src/Umbraco.Core/Services/IContentService.cs b/src/Umbraco.Core/Services/IContentService.cs index e33f46e3f4..4caa295659 100644 --- a/src/Umbraco.Core/Services/IContentService.cs +++ b/src/Umbraco.Core/Services/IContentService.cs @@ -162,6 +162,22 @@ namespace Umbraco.Core.Services IEnumerable GetByIds(IEnumerable ids); + /// + /// Creates an object using the alias of the + /// that this Content should based on. + /// + /// + /// Note that using this method will simply return a new IContent without any identity + /// as it has not yet been persisted. It is intended as a shortcut to creating new content objects + /// that does not invoke a save operation against the database. + /// + /// Name of the Content object + /// Id of Parent for the new Content + /// Alias of the + /// Optional id of the user creating the content + /// + IContent CreateContent(string name, Guid parentId, string contentTypeAlias, int userId = 0); + /// /// Creates an object using the alias of the /// that this Content should based on. diff --git a/src/Umbraco.Core/Services/IMediaService.cs b/src/Umbraco.Core/Services/IMediaService.cs index 8cd2b0eed5..8ef126c198 100644 --- a/src/Umbraco.Core/Services/IMediaService.cs +++ b/src/Umbraco.Core/Services/IMediaService.cs @@ -88,6 +88,22 @@ namespace Umbraco.Core.Services IEnumerable GetByIds(IEnumerable ids); + /// + /// Creates an object using the alias of the + /// that this Media should based on. + /// + /// + /// Note that using this method will simply return a new IMedia without any identity + /// as it has not yet been persisted. It is intended as a shortcut to creating new media objects + /// that does not invoke a save operation against the database. + /// + /// Name of the Media object + /// Id of Parent for the new Media item + /// Alias of the + /// Optional id of the user creating the media item + /// + IMedia CreateMedia(string name, Guid parentId, string mediaTypeAlias, int userId = 0); + /// /// Creates an object using the alias of the /// that this Media should based on. diff --git a/src/Umbraco.Core/Services/MediaService.cs b/src/Umbraco.Core/Services/MediaService.cs index 38c0c20eb2..6476e9a86d 100644 --- a/src/Umbraco.Core/Services/MediaService.cs +++ b/src/Umbraco.Core/Services/MediaService.cs @@ -45,7 +45,27 @@ namespace Umbraco.Core.Services _dataTypeService = dataTypeService; _userService = userService; _idkMap = idkMap; - } + } + + /// + /// Creates an object using the alias of the + /// that this Media should based on. + /// + /// + /// Note that using this method will simply return a new IMedia without any identity + /// as it has not yet been persisted. It is intended as a shortcut to creating new media objects + /// that does not invoke a save operation against the database. + /// + /// Name of the Media object + /// Id of Parent for the new Media item + /// Alias of the + /// Optional id of the user creating the media item + /// + public IMedia CreateMedia(string name, Guid parentId, string mediaTypeAlias, int userId = 0) + { + var parent = GetById(parentId); + return CreateMedia(name, parent, mediaTypeAlias, userId); + } /// /// Creates an object using the alias of the diff --git a/src/Umbraco.Core/Services/MediaServiceExtensions.cs b/src/Umbraco.Core/Services/MediaServiceExtensions.cs new file mode 100644 index 0000000000..3e3dea1a4a --- /dev/null +++ b/src/Umbraco.Core/Services/MediaServiceExtensions.cs @@ -0,0 +1,24 @@ +using System; +using Umbraco.Core.Models; + +namespace Umbraco.Core.Services +{ + /// + /// Media service extension methods + /// + /// + /// Many of these have to do with UDI lookups but we don't need to add these methods to the service interface since a UDI is just a GUID + /// and the services already support GUIDs + /// + public static class MediaServiceExtensions + { + public static IMedia CreateMedia(this IMediaService mediaService, string name, Udi parentId, string mediaTypeAlias, int userId = 0) + { + var guidUdi = parentId as GuidUdi; + if (guidUdi == null) + throw new InvalidOperationException("The UDI provided isn't of type " + typeof(GuidUdi) + " which is required by media"); + var parent = mediaService.GetById(guidUdi.Guid); + return mediaService.CreateMedia(name, parent, mediaTypeAlias, userId); + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 96183f61bf..a676d8caa3 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -705,6 +705,7 @@ + From 558a2847506b27d792b1584b6535eb49aa32c634 Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 10 Aug 2017 01:01:07 +1000 Subject: [PATCH 2/7] U4-10263 Missing UDI + GUID friendly MediaService.GetByIds, ContentService.GetByIds --- .../Repositories/ContentRepository.cs | 102 ++++++++++++++++- .../Interfaces/IContentRepository.cs | 2 +- .../Interfaces/IMediaRepository.cs | 3 +- .../Repositories/MediaRepository.cs | 108 ++++++++++++++++++ src/Umbraco.Core/Services/ContentService.cs | 30 ++++- src/Umbraco.Core/Services/IContentService.cs | 1 + src/Umbraco.Core/Services/IMediaService.cs | 1 + src/Umbraco.Core/Services/MediaService.cs | 18 ++- .../Repositories/ContentRepositoryTest.cs | 10 ++ .../Repositories/MediaRepositoryTest.cs | 10 ++ 10 files changed, 279 insertions(+), 6 deletions(-) diff --git a/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs b/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs index addd0bc925..821af8966e 100644 --- a/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs @@ -31,6 +31,7 @@ namespace Umbraco.Core.Persistence.Repositories private readonly ContentPreviewRepository _contentPreviewRepository; private readonly ContentXmlRepository _contentXmlRepository; private readonly PermissionRepository _permissionRepository; + private readonly ContentByGuidReadRepository _contentByGuidReadRepository; public ContentRepository(IScopeUnitOfWork work, CacheHelper cacheHelper, ILogger logger, ISqlSyntaxProvider syntaxProvider, IContentTypeRepository contentTypeRepository, ITemplateRepository templateRepository, ITagRepository tagRepository, IContentSection contentSection) : base(work, cacheHelper, logger, syntaxProvider, contentSection) @@ -44,7 +45,7 @@ namespace Umbraco.Core.Persistence.Repositories _contentPreviewRepository = new ContentPreviewRepository(work, CacheHelper.NoCache, logger, syntaxProvider); _contentXmlRepository = new ContentXmlRepository(work, CacheHelper.NoCache, logger, syntaxProvider); _permissionRepository = new PermissionRepository(UnitOfWork, cacheHelper, Logger, SqlSyntax); - + _contentByGuidReadRepository = new ContentByGuidReadRepository(this, work, cacheHelper, logger, syntaxProvider); EnsureUniqueNaming = true; } @@ -938,6 +939,105 @@ order by umbracoNode.{2}, umbracoNode.parentID, umbracoNode.sortOrder", #endregion + #region Read Repository implementation for GUID keys + public IContent Get(Guid id) + { + return _contentByGuidReadRepository.Get(id); + } + + IEnumerable IReadRepository.GetAll(params Guid[] ids) + { + return _contentByGuidReadRepository.GetAll(ids); + } + + public bool Exists(Guid id) + { + return _contentByGuidReadRepository.Exists(id); + } + + /// + /// A reading repository purely for looking up by GUID + /// + /// + /// TODO: This is ugly and to fix we need to decouple the IRepositoryQueryable -> IRepository -> IReadRepository which should all be separate things! + /// Then we can do the same thing with repository instances and we wouldn't need to leave all these methods as not implemented because we wouldn't need to implement them + /// + private class ContentByGuidReadRepository : PetaPocoRepositoryBase + { + private readonly ContentRepository _outerRepo; + + public ContentByGuidReadRepository(ContentRepository outerRepo, + IScopeUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax) + : base(work, cache, logger, sqlSyntax) + { + _outerRepo = outerRepo; + } + + protected override IContent PerformGet(Guid id) + { + var sql = _outerRepo.GetBaseQuery(BaseQueryType.FullSingle) + .Where(GetBaseWhereClause(), new { Id = id }) + .Where(x => x.Newest, SqlSyntax) + .OrderByDescending(x => x.VersionDate, SqlSyntax); + + var dto = Database.Fetch(SqlSyntax.SelectTop(sql, 1)).FirstOrDefault(); + + if (dto == null) + return null; + + var content = _outerRepo.CreateContentFromDto(dto, sql); + + return content; + } + + protected override IEnumerable PerformGetAll(params Guid[] ids) + { + var sql = GetBaseQuery(false); + if (ids.Any()) + { + sql.Where("umbracoNode.uniqueID in (@ids)", new { ids = ids }); + } + + return _outerRepo.ProcessQuery(sql, new PagingSqlQuery(sql)); + } + + protected override Sql GetBaseQuery(bool isCount) + { + return _outerRepo.GetBaseQuery(isCount); + } + + protected override string GetBaseWhereClause() + { + return "umbracoNode.uniqueID = @Id"; + } + + protected override Guid NodeObjectTypeId + { + get { return _outerRepo.NodeObjectTypeId; } + } + + #region Not needed to implement + + protected override IEnumerable PerformGetByQuery(IQuery query) + { + throw new NotImplementedException(); + } + protected override IEnumerable GetDeleteClauses() + { + throw new NotImplementedException(); + } + protected override void PersistNewItem(IContent entity) + { + throw new NotImplementedException(); + } + protected override void PersistUpdatedItem(IContent entity) + { + throw new NotImplementedException(); + } + #endregion + } + #endregion + protected override string GetDatabaseFieldNameForOrderBy(string orderBy) { //Some custom ones diff --git a/src/Umbraco.Core/Persistence/Repositories/Interfaces/IContentRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Interfaces/IContentRepository.cs index c019b694d2..c98f073f40 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Interfaces/IContentRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Interfaces/IContentRepository.cs @@ -11,7 +11,7 @@ using Umbraco.Core.Persistence.Querying; namespace Umbraco.Core.Persistence.Repositories { - public interface IContentRepository : IRepositoryVersionable, IRecycleBinRepository, IDeleteMediaFilesRepository + public interface IContentRepository : IRepositoryVersionable, IRecycleBinRepository, IReadRepository, IDeleteMediaFilesRepository { /// /// This builds the Xml document used for the XML cache diff --git a/src/Umbraco.Core/Persistence/Repositories/Interfaces/IMediaRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Interfaces/IMediaRepository.cs index 4c9b1d3561..b6a22ba761 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Interfaces/IMediaRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Interfaces/IMediaRepository.cs @@ -7,9 +7,8 @@ using Umbraco.Core.Persistence.Querying; namespace Umbraco.Core.Persistence.Repositories { - public interface IMediaRepository : IRepositoryVersionable, IRecycleBinRepository, IDeleteMediaFilesRepository + public interface IMediaRepository : IRepositoryVersionable, IRecycleBinRepository, IReadRepository, IDeleteMediaFilesRepository { - /// /// Used to add/update published xml for the media item /// diff --git a/src/Umbraco.Core/Persistence/Repositories/MediaRepository.cs b/src/Umbraco.Core/Persistence/Repositories/MediaRepository.cs index ee413c2a59..828ae843f8 100644 --- a/src/Umbraco.Core/Persistence/Repositories/MediaRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/MediaRepository.cs @@ -27,6 +27,7 @@ namespace Umbraco.Core.Persistence.Repositories private readonly ITagRepository _tagRepository; private readonly ContentXmlRepository _contentXmlRepository; private readonly ContentPreviewRepository _contentPreviewRepository; + private readonly MediaByGuidReadRepository _mediaByGuidReadRepository; public MediaRepository(IScopeUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax, IMediaTypeRepository mediaTypeRepository, ITagRepository tagRepository, IContentSection contentSection) : base(work, cache, logger, sqlSyntax, contentSection) @@ -37,6 +38,7 @@ namespace Umbraco.Core.Persistence.Repositories _tagRepository = tagRepository; _contentXmlRepository = new ContentXmlRepository(work, CacheHelper.NoCache, logger, sqlSyntax); _contentPreviewRepository = new ContentPreviewRepository(work, CacheHelper.NoCache, logger, sqlSyntax); + _mediaByGuidReadRepository = new MediaByGuidReadRepository(this, work, cache, logger, sqlSyntax); EnsureUniqueNaming = contentSection.EnsureUniqueNaming; } @@ -522,6 +524,112 @@ namespace Umbraco.Core.Persistence.Repositories #endregion + #region Read Repository implementation for GUID keys + public IMedia Get(Guid id) + { + return _mediaByGuidReadRepository.Get(id); + } + + IEnumerable IReadRepository.GetAll(params Guid[] ids) + { + return _mediaByGuidReadRepository.GetAll(ids); + } + + public bool Exists(Guid id) + { + return _mediaByGuidReadRepository.Exists(id); + } + + /// + /// A reading repository purely for looking up by GUID + /// + /// + /// TODO: This is ugly and to fix we need to decouple the IRepositoryQueryable -> IRepository -> IReadRepository which should all be separate things! + /// Then we can do the same thing with repository instances and we wouldn't need to leave all these methods as not implemented because we wouldn't need to implement them + /// + private class MediaByGuidReadRepository : PetaPocoRepositoryBase + { + private readonly MediaRepository _outerRepo; + + public MediaByGuidReadRepository(MediaRepository outerRepo, + IScopeUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax) + : base(work, cache, logger, sqlSyntax) + { + _outerRepo = outerRepo; + } + + protected override IMedia PerformGet(Guid id) + { + var sql = GetBaseQuery(false); + sql.Where(GetBaseWhereClause(), new { Id = id }); + sql.OrderByDescending(x => x.VersionDate, SqlSyntax); + + var dto = Database.Fetch(SqlSyntax.SelectTop(sql, 1)).FirstOrDefault(); + + if (dto == null) + return null; + + var content = _outerRepo.CreateMediaFromDto(dto, sql); + + return content; + } + + protected override IEnumerable PerformGetAll(params Guid[] ids) + { + Func translate = s => + { + if (ids.Any()) + { + s.Where("umbracoNode.uniqueID in (@ids)", new { ids }); + } + //we only want the newest ones with this method + s.Where(x => x.Newest, SqlSyntax); + return s; + }; + + var sqlBaseFull = _outerRepo.GetBaseQuery(BaseQueryType.FullMultiple); + var sqlBaseIds = _outerRepo.GetBaseQuery(BaseQueryType.Ids); + + return _outerRepo.ProcessQuery(translate(sqlBaseFull), new PagingSqlQuery(translate(sqlBaseIds))); + } + + protected override Sql GetBaseQuery(bool isCount) + { + return _outerRepo.GetBaseQuery(isCount); + } + + protected override string GetBaseWhereClause() + { + return "umbracoNode.uniqueID = @Id"; + } + + protected override Guid NodeObjectTypeId + { + get { return _outerRepo.NodeObjectTypeId; } + } + + #region Not needed to implement + + protected override IEnumerable PerformGetByQuery(IQuery query) + { + throw new NotImplementedException(); + } + protected override IEnumerable GetDeleteClauses() + { + throw new NotImplementedException(); + } + protected override void PersistNewItem(IMedia entity) + { + throw new NotImplementedException(); + } + protected override void PersistUpdatedItem(IMedia entity) + { + throw new NotImplementedException(); + } + #endregion + } + #endregion + /// /// Gets paged media results /// diff --git a/src/Umbraco.Core/Services/ContentService.cs b/src/Umbraco.Core/Services/ContentService.cs index b635caef5b..e6f402de46 100644 --- a/src/Umbraco.Core/Services/ContentService.cs +++ b/src/Umbraco.Core/Services/ContentService.cs @@ -369,7 +369,7 @@ namespace Umbraco.Core.Services } /// - /// Gets an object by Id + /// Gets an objects by Ids /// /// Ids of the Content to retrieve /// @@ -396,6 +396,34 @@ namespace Umbraco.Core.Services } } + /// + /// Gets an objects by Ids + /// + /// Ids of the Content to retrieve + /// + public IEnumerable GetByIds(IEnumerable ids) + { + var idsArray = ids.ToArray(); + if (idsArray.Length == 0) return Enumerable.Empty(); + + using (var uow = UowProvider.GetUnitOfWork(readOnly: true)) + { + var repository = RepositoryFactory.CreateContentRepository(uow); + + // ensure that the result has the order based on the ids passed in + var result = repository.GetAll(idsArray); + var content = result.ToDictionary(x => x.Key, x => x); + + var sortedResult = idsArray.Select(x => + { + IContent c; + return content.TryGetValue(x, out c) ? c : null; + }).WhereNotNull(); + + return sortedResult; + } + } + /// /// Gets an object by its 'UniqueId' /// diff --git a/src/Umbraco.Core/Services/IContentService.cs b/src/Umbraco.Core/Services/IContentService.cs index 4caa295659..7a5c64c0c0 100644 --- a/src/Umbraco.Core/Services/IContentService.cs +++ b/src/Umbraco.Core/Services/IContentService.cs @@ -161,6 +161,7 @@ namespace Umbraco.Core.Services bool SendToPublication(IContent content, int userId = 0); IEnumerable GetByIds(IEnumerable ids); + IEnumerable GetByIds(IEnumerable ids); /// /// Creates an object using the alias of the diff --git a/src/Umbraco.Core/Services/IMediaService.cs b/src/Umbraco.Core/Services/IMediaService.cs index 8ef126c198..04683e5747 100644 --- a/src/Umbraco.Core/Services/IMediaService.cs +++ b/src/Umbraco.Core/Services/IMediaService.cs @@ -87,6 +87,7 @@ namespace Umbraco.Core.Services int CountDescendants(int parentId, string contentTypeAlias = null); IEnumerable GetByIds(IEnumerable ids); + IEnumerable GetByIds(IEnumerable ids); /// /// Creates an object using the alias of the diff --git a/src/Umbraco.Core/Services/MediaService.cs b/src/Umbraco.Core/Services/MediaService.cs index 6476e9a86d..28b1275823 100644 --- a/src/Umbraco.Core/Services/MediaService.cs +++ b/src/Umbraco.Core/Services/MediaService.cs @@ -327,7 +327,7 @@ namespace Umbraco.Core.Services } /// - /// Gets an object by Id + /// Gets an objects by Ids /// /// Ids of the Media to retrieve /// @@ -342,6 +342,22 @@ namespace Umbraco.Core.Services } } + /// + /// Gets an objects by Ids + /// + /// Ids of the Media to retrieve + /// + public IEnumerable GetByIds(IEnumerable ids) + { + if (ids.Any() == false) return Enumerable.Empty(); + + using (var uow = UowProvider.GetUnitOfWork(readOnly: true)) + { + var repository = RepositoryFactory.CreateMediaRepository(uow); + return repository.GetAll(ids.ToArray()); + } + } + /// /// Gets an object by its 'UniqueId' /// diff --git a/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs index f969488055..9301efa68a 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs @@ -1039,6 +1039,16 @@ namespace Umbraco.Tests.Persistence.Repositories Assert.That(contents, Is.Not.Null); Assert.That(contents.Any(), Is.True); Assert.That(contents.Count(), Is.GreaterThanOrEqualTo(4)); + + contents = repository.GetAll(contents.Select(x => x.Id).ToArray()); + Assert.That(contents, Is.Not.Null); + Assert.That(contents.Any(), Is.True); + Assert.That(contents.Count(), Is.GreaterThanOrEqualTo(4)); + + contents = ((IReadRepository)repository).GetAll(contents.Select(x => x.Key).ToArray()); + Assert.That(contents, Is.Not.Null); + Assert.That(contents.Any(), Is.True); + Assert.That(contents.Count(), Is.GreaterThanOrEqualTo(4)); } diff --git a/src/Umbraco.Tests/Persistence/Repositories/MediaRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/MediaRepositoryTest.cs index c9f78fb201..e0ad754195 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/MediaRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/MediaRepositoryTest.cs @@ -627,6 +627,16 @@ namespace Umbraco.Tests.Persistence.Repositories Assert.That(medias, Is.Not.Null); Assert.That(medias.Any(), Is.True); Assert.That(medias.Count(), Is.GreaterThanOrEqualTo(3)); + + medias = repository.GetAll(medias.Select(x => x.Id).ToArray()); + Assert.That(medias, Is.Not.Null); + Assert.That(medias.Any(), Is.True); + Assert.That(medias.Count(), Is.GreaterThanOrEqualTo(4)); + + medias = ((IReadRepository)repository).GetAll(medias.Select(x => x.Key).ToArray()); + Assert.That(medias, Is.Not.Null); + Assert.That(medias.Any(), Is.True); + Assert.That(medias.Count(), Is.GreaterThanOrEqualTo(4)); } } From 8f121c4d93d38fafce893558e40fde3944648142 Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 10 Aug 2017 01:01:34 +1000 Subject: [PATCH 3/7] update test --- .../Persistence/Repositories/MediaRepositoryTest.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Tests/Persistence/Repositories/MediaRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/MediaRepositoryTest.cs index e0ad754195..4dfaccd7ab 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/MediaRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/MediaRepositoryTest.cs @@ -631,12 +631,12 @@ namespace Umbraco.Tests.Persistence.Repositories medias = repository.GetAll(medias.Select(x => x.Id).ToArray()); Assert.That(medias, Is.Not.Null); Assert.That(medias.Any(), Is.True); - Assert.That(medias.Count(), Is.GreaterThanOrEqualTo(4)); + Assert.That(medias.Count(), Is.GreaterThanOrEqualTo(3)); medias = ((IReadRepository)repository).GetAll(medias.Select(x => x.Key).ToArray()); Assert.That(medias, Is.Not.Null); Assert.That(medias.Any(), Is.True); - Assert.That(medias.Count(), Is.GreaterThanOrEqualTo(4)); + Assert.That(medias.Count(), Is.GreaterThanOrEqualTo(3)); } } From 2c219576f6188b960b32a025a27e96cd1b7b0f45 Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 10 Aug 2017 01:08:29 +1000 Subject: [PATCH 4/7] update test --- .../Repositories/ContentRepository.cs | 18 +++++++++++++----- .../Repositories/MediaRepository.cs | 18 +++++------------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs b/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs index 821af8966e..236f0ed311 100644 --- a/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs @@ -992,13 +992,21 @@ order by umbracoNode.{2}, umbracoNode.parentID, umbracoNode.sortOrder", protected override IEnumerable PerformGetAll(params Guid[] ids) { - var sql = GetBaseQuery(false); - if (ids.Any()) + Func translate = s => { - sql.Where("umbracoNode.uniqueID in (@ids)", new { ids = ids }); - } + if (ids.Any()) + { + s.Where("umbracoNode.uniqueID in (@ids)", new { ids }); + } + //we only want the newest ones with this method + s.Where(x => x.Newest, SqlSyntax); + return s; + }; - return _outerRepo.ProcessQuery(sql, new PagingSqlQuery(sql)); + var sqlBaseFull = _outerRepo.GetBaseQuery(BaseQueryType.FullMultiple); + var sqlBaseIds = _outerRepo.GetBaseQuery(BaseQueryType.Ids); + + return _outerRepo.ProcessQuery(translate(sqlBaseFull), new PagingSqlQuery(translate(sqlBaseIds))); } protected override Sql GetBaseQuery(bool isCount) diff --git a/src/Umbraco.Core/Persistence/Repositories/MediaRepository.cs b/src/Umbraco.Core/Persistence/Repositories/MediaRepository.cs index 828ae843f8..ad2dd26a43 100644 --- a/src/Umbraco.Core/Persistence/Repositories/MediaRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/MediaRepository.cs @@ -576,21 +576,13 @@ namespace Umbraco.Core.Persistence.Repositories protected override IEnumerable PerformGetAll(params Guid[] ids) { - Func translate = s => + var sql = GetBaseQuery(false); + if (ids.Any()) { - if (ids.Any()) - { - s.Where("umbracoNode.uniqueID in (@ids)", new { ids }); - } - //we only want the newest ones with this method - s.Where(x => x.Newest, SqlSyntax); - return s; - }; + sql.Where("umbracoNode.uniqueID in (@ids)", new { ids = ids }); + } - var sqlBaseFull = _outerRepo.GetBaseQuery(BaseQueryType.FullMultiple); - var sqlBaseIds = _outerRepo.GetBaseQuery(BaseQueryType.Ids); - - return _outerRepo.ProcessQuery(translate(sqlBaseFull), new PagingSqlQuery(translate(sqlBaseIds))); + return _outerRepo.ProcessQuery(sql, new PagingSqlQuery(sql)); } protected override Sql GetBaseQuery(bool isCount) From bdf621049f2fb9d824ee3f92c102cd2af2277655 Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 10 Aug 2017 01:11:59 +1000 Subject: [PATCH 5/7] adds GetByIds for UDIs --- .../Services/ContentServiceExtensions.cs | 14 ++++++++++++++ .../Services/MediaServiceExtensions.cs | 16 ++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/src/Umbraco.Core/Services/ContentServiceExtensions.cs b/src/Umbraco.Core/Services/ContentServiceExtensions.cs index d7f9c52d38..6e3f75c42d 100644 --- a/src/Umbraco.Core/Services/ContentServiceExtensions.cs +++ b/src/Umbraco.Core/Services/ContentServiceExtensions.cs @@ -14,6 +14,20 @@ namespace Umbraco.Core.Services /// public static class ContentServiceExtensions { + public static IEnumerable GetByIds(this IContentService contentService, IEnumerable ids) + { + var guids = new List(); + foreach (var udi in ids) + { + var guidUdi = udi as GuidUdi; + if (guidUdi == null) + throw new InvalidOperationException("The UDI provided isn't of type " + typeof(GuidUdi) + " which is required by content"); + guids.Add(guidUdi); + } + + return contentService.GetByIds(guids.Select(x => x.Guid)); + } + /// /// Method to create an IContent object based on the Udi of a parent /// diff --git a/src/Umbraco.Core/Services/MediaServiceExtensions.cs b/src/Umbraco.Core/Services/MediaServiceExtensions.cs index 3e3dea1a4a..41e0ebe55e 100644 --- a/src/Umbraco.Core/Services/MediaServiceExtensions.cs +++ b/src/Umbraco.Core/Services/MediaServiceExtensions.cs @@ -1,4 +1,6 @@ using System; +using System.Collections.Generic; +using System.Linq; using Umbraco.Core.Models; namespace Umbraco.Core.Services @@ -12,6 +14,20 @@ namespace Umbraco.Core.Services /// public static class MediaServiceExtensions { + public static IEnumerable GetByIds(this IMediaService mediaService, IEnumerable ids) + { + var guids = new List(); + foreach (var udi in ids) + { + var guidUdi = udi as GuidUdi; + if (guidUdi == null) + throw new InvalidOperationException("The UDI provided isn't of type " + typeof(GuidUdi) + " which is required by media"); + guids.Add(guidUdi); + } + + return mediaService.GetByIds(guids.Select(x => x.Guid)); + } + public static IMedia CreateMedia(this IMediaService mediaService, string name, Udi parentId, string mediaTypeAlias, int userId = 0) { var guidUdi = parentId as GuidUdi; From a97a5dc3fdcf85c3e791530a0fd2d225e74fd002 Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 10 Aug 2017 10:52:31 +1000 Subject: [PATCH 6/7] Removes need for the IdkMap for content/media services since we have a wrapping repo now, adds tests to verify that caching is active for both INT and GUID --- src/Umbraco.Core/Services/ContentService.cs | 32 ++++----- src/Umbraco.Core/Services/MediaService.cs | 18 ++--- src/Umbraco.Core/Services/ServiceContext.cs | 4 +- .../Repositories/ContentRepositoryTest.cs | 67 ++++++++++++++++--- .../Repositories/MediaRepositoryTest.cs | 57 ++++++++++++++-- 5 files changed, 131 insertions(+), 47 deletions(-) diff --git a/src/Umbraco.Core/Services/ContentService.cs b/src/Umbraco.Core/Services/ContentService.cs index e6f402de46..49d745f0cf 100644 --- a/src/Umbraco.Core/Services/ContentService.cs +++ b/src/Umbraco.Core/Services/ContentService.cs @@ -32,7 +32,6 @@ namespace Umbraco.Core.Services private readonly EntityXmlSerializer _entitySerializer = new EntityXmlSerializer(); private readonly IDataTypeService _dataTypeService; private readonly IUserService _userService; - private readonly IdkMap _idkMap; //Support recursive locks because some of the methods that require locking call other methods that require locking. //for example, the Move method needs to be locked but this calls the Save method which also needs to be locked. @@ -44,8 +43,7 @@ namespace Umbraco.Core.Services ILogger logger, IEventMessagesFactory eventMessagesFactory, IDataTypeService dataTypeService, - IUserService userService, - IdkMap idkMap) + IUserService userService) : base(provider, repositoryFactory, logger, eventMessagesFactory) { if (dataTypeService == null) throw new ArgumentNullException("dataTypeService"); @@ -53,7 +51,6 @@ namespace Umbraco.Core.Services _publishingStrategy = new PublishingStrategy(UowProvider.ScopeProvider, eventMessagesFactory, logger); _dataTypeService = dataTypeService; _userService = userService; - _idkMap = idkMap; } #region Static Queries @@ -431,13 +428,11 @@ namespace Umbraco.Core.Services /// public IContent GetById(Guid key) { - // the repository implements a cache policy on int identifiers, not guids, - // and we are not changing it now, but we still would like to rely on caching - // instead of running a full query against the database, so relying on the - // id-key map, which is fast. - - var a = _idkMap.GetIdForKey(key, UmbracoObjectTypes.Document); - return a.Success ? GetById(a.Result) : null; + using (var uow = UowProvider.GetUnitOfWork(readOnly: true)) + { + var repository = RepositoryFactory.CreateContentRepository(uow); + return repository.Get(key); + } } /// @@ -1218,13 +1213,14 @@ namespace Umbraco.Core.Services public IContent GetBlueprintById(Guid id) { - // the repository implements a cache policy on int identifiers, not guids, - // and we are not changing it now, but we still would like to rely on caching - // instead of running a full query against the database, so relying on the - // id-key map, which is fast. - - var a = _idkMap.GetIdForKey(id, UmbracoObjectTypes.DocumentBlueprint); - return a.Success ? GetBlueprintById(a.Result) : null; + using (var uow = UowProvider.GetUnitOfWork(readOnly: true)) + { + var repository = RepositoryFactory.CreateContentBlueprintRepository(uow); + var blueprint = repository.Get(id); + if (blueprint != null) + ((Content)blueprint).IsBlueprint = true; + return blueprint; + } } public void SaveBlueprint(IContent content, int userId = 0) diff --git a/src/Umbraco.Core/Services/MediaService.cs b/src/Umbraco.Core/Services/MediaService.cs index 28b1275823..ee4cddb382 100644 --- a/src/Umbraco.Core/Services/MediaService.cs +++ b/src/Umbraco.Core/Services/MediaService.cs @@ -35,16 +35,14 @@ namespace Umbraco.Core.Services private readonly IDataTypeService _dataTypeService; private readonly IUserService _userService; private readonly MediaFileSystem _mediaFileSystem = FileSystemProviderManager.Current.MediaFileSystem; - private readonly IdkMap _idkMap; - public MediaService(IDatabaseUnitOfWorkProvider provider, RepositoryFactory repositoryFactory, ILogger logger, IEventMessagesFactory eventMessagesFactory, IDataTypeService dataTypeService, IUserService userService, IdkMap idkMap) + public MediaService(IDatabaseUnitOfWorkProvider provider, RepositoryFactory repositoryFactory, ILogger logger, IEventMessagesFactory eventMessagesFactory, IDataTypeService dataTypeService, IUserService userService) : base(provider, repositoryFactory, logger, eventMessagesFactory) { if (dataTypeService == null) throw new ArgumentNullException("dataTypeService"); if (userService == null) throw new ArgumentNullException("userService"); _dataTypeService = dataTypeService; _userService = userService; - _idkMap = idkMap; } /// @@ -365,15 +363,11 @@ namespace Umbraco.Core.Services /// public IMedia GetById(Guid key) { - // the repository implements a cache policy on int identifiers, not guids, - // and we are not changing it now, but we still would like to rely on caching - // instead of running a full query against the database, so relying on the - // id-key map, which is fast. - // - // we should inject the id-key map but ... breaking changes ... yada - - var a = _idkMap.GetIdForKey(key, UmbracoObjectTypes.Media); - return a.Success ? GetById(a.Result) : null; + using (var uow = UowProvider.GetUnitOfWork(readOnly: true)) + { + var repository = RepositoryFactory.CreateMediaRepository(uow); + return repository.Get(key); + } } /// diff --git a/src/Umbraco.Core/Services/ServiceContext.cs b/src/Umbraco.Core/Services/ServiceContext.cs index 3da10e132b..144d548b78 100644 --- a/src/Umbraco.Core/Services/ServiceContext.cs +++ b/src/Umbraco.Core/Services/ServiceContext.cs @@ -261,10 +261,10 @@ namespace Umbraco.Core.Services _memberService = new Lazy(() => new MemberService(provider, repositoryFactory, logger, eventMessagesFactory, _memberGroupService.Value, _dataTypeService.Value)); if (_contentService == null) - _contentService = new Lazy(() => new ContentService(provider, repositoryFactory, logger, eventMessagesFactory, _dataTypeService.Value, _userService.Value, idkMap)); + _contentService = new Lazy(() => new ContentService(provider, repositoryFactory, logger, eventMessagesFactory, _dataTypeService.Value, _userService.Value)); if (_mediaService == null) - _mediaService = new Lazy(() => new MediaService(provider, repositoryFactory, logger, eventMessagesFactory, _dataTypeService.Value, _userService.Value, idkMap)); + _mediaService = new Lazy(() => new MediaService(provider, repositoryFactory, logger, eventMessagesFactory, _dataTypeService.Value, _userService.Value)); if (_contentTypeService == null) _contentTypeService = new Lazy(() => new ContentTypeService(provider, repositoryFactory, logger, eventMessagesFactory, _contentService.Value, _mediaService.Value)); diff --git a/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs index 9301efa68a..8814ef229e 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs @@ -2,10 +2,12 @@ using System.Collections.Generic; using System.Globalization; using System.Linq; +using System.Web; using System.Xml.Linq; using Moq; using NUnit.Framework; using Umbraco.Core; +using Umbraco.Core.Cache; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.IO; using Umbraco.Core.Models; @@ -41,32 +43,75 @@ namespace Umbraco.Tests.Persistence.Repositories base.TearDown(); } - private ContentRepository CreateRepository(IScopeUnitOfWork unitOfWork, out ContentTypeRepository contentTypeRepository, out DataTypeDefinitionRepository dtdRepository) + private ContentRepository CreateRepository(IScopeUnitOfWork unitOfWork, out ContentTypeRepository contentTypeRepository, out DataTypeDefinitionRepository dtdRepository, CacheHelper cacheHelper = null) { TemplateRepository tr; var ctRepository = CreateRepository(unitOfWork, out contentTypeRepository, out tr); - dtdRepository = new DataTypeDefinitionRepository(unitOfWork, CacheHelper, Logger, SqlSyntax, contentTypeRepository); + dtdRepository = new DataTypeDefinitionRepository(unitOfWork, cacheHelper, Logger, SqlSyntax, contentTypeRepository); return ctRepository; } - private ContentRepository CreateRepository(IScopeUnitOfWork unitOfWork, out ContentTypeRepository contentTypeRepository) + private ContentRepository CreateRepository(IScopeUnitOfWork unitOfWork, out ContentTypeRepository contentTypeRepository, CacheHelper cacheHelper = null) { TemplateRepository tr; - return CreateRepository(unitOfWork, out contentTypeRepository, out tr); + return CreateRepository(unitOfWork, out contentTypeRepository, out tr, cacheHelper); } - private ContentRepository CreateRepository(IScopeUnitOfWork unitOfWork, out ContentTypeRepository contentTypeRepository, out TemplateRepository templateRepository) + private ContentRepository CreateRepository(IScopeUnitOfWork unitOfWork, out ContentTypeRepository contentTypeRepository, out TemplateRepository templateRepository, CacheHelper cacheHelper = null) { - templateRepository = new TemplateRepository(unitOfWork, CacheHelper, Logger, SqlSyntax, Mock.Of(), Mock.Of(), Mock.Of()); - var tagRepository = new TagRepository(unitOfWork, CacheHelper, Logger, SqlSyntax); - contentTypeRepository = new ContentTypeRepository(unitOfWork, CacheHelper, Logger, SqlSyntax, templateRepository); - var repository = new ContentRepository(unitOfWork, CacheHelper, Logger, SqlSyntax, contentTypeRepository, templateRepository, tagRepository, Mock.Of()); + cacheHelper = cacheHelper ?? CacheHelper; + + templateRepository = new TemplateRepository(unitOfWork, cacheHelper, Logger, SqlSyntax, Mock.Of(), Mock.Of(), Mock.Of()); + var tagRepository = new TagRepository(unitOfWork, cacheHelper, Logger, SqlSyntax); + contentTypeRepository = new ContentTypeRepository(unitOfWork, cacheHelper, Logger, SqlSyntax, templateRepository); + var repository = new ContentRepository(unitOfWork, cacheHelper, Logger, SqlSyntax, contentTypeRepository, templateRepository, tagRepository, Mock.Of()); return repository; } - private UserGroupRepository CreateUserGroupRepository(IScopeUnitOfWork unitOfWork) + [Test] + public void Cache_Active_By_Int_And_Guid() { - return new UserGroupRepository(unitOfWork, CacheHelper, Logger, SqlSyntax); + var provider = new PetaPocoUnitOfWorkProvider(Logger); + var unitOfWork = provider.GetUnitOfWork(); + ContentTypeRepository contentTypeRepository; + + var realCache = new CacheHelper( + new ObjectCacheRuntimeCacheProvider(), + new StaticCacheProvider(), + new StaticCacheProvider(), + new IsolatedRuntimeCache(t => new ObjectCacheRuntimeCacheProvider())); + + using (var repository = CreateRepository(unitOfWork, out contentTypeRepository, cacheHelper: realCache)) + { + DatabaseContext.Database.DisableSqlCount(); + + var contentType = MockedContentTypes.CreateSimpleContentType("umbTextpage1", "Textpage"); + var content = MockedContent.CreateSimpleContent(contentType); + contentTypeRepository.AddOrUpdate(contentType); + repository.AddOrUpdate(content); + unitOfWork.Commit(); + + DatabaseContext.Database.EnableSqlCount(); + + //go get it, this should already be cached since the default repository key is the INT + var found = repository.Get(content.Id); + Assert.AreEqual(0, DatabaseContext.Database.SqlCount); + //retrieve again, this should use cache + found = repository.Get(content.Id); + Assert.AreEqual(0, DatabaseContext.Database.SqlCount); + + //reset counter + DatabaseContext.Database.DisableSqlCount(); + DatabaseContext.Database.EnableSqlCount(); + + //now get by GUID, this won't be cached yet because the default repo key is not a GUID + found = repository.Get(content.Key); + var sqlCount = DatabaseContext.Database.SqlCount; + Assert.Greater(sqlCount, 0); + //retrieve again, this should use cache now + found = repository.Get(content.Key); + Assert.AreEqual(sqlCount, DatabaseContext.Database.SqlCount); + } } [Test] diff --git a/src/Umbraco.Tests/Persistence/Repositories/MediaRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/MediaRepositoryTest.cs index 4dfaccd7ab..a2f82b0ad0 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/MediaRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/MediaRepositoryTest.cs @@ -5,6 +5,7 @@ using System.Xml.Linq; using Moq; using NUnit.Framework; using Umbraco.Core; +using Umbraco.Core.Cache; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Logging; using Umbraco.Core.Models; @@ -35,14 +36,62 @@ namespace Umbraco.Tests.Persistence.Repositories CreateTestData(); } - private MediaRepository CreateRepository(IScopeUnitOfWork unitOfWork, out MediaTypeRepository mediaTypeRepository) + private MediaRepository CreateRepository(IScopeUnitOfWork unitOfWork, out MediaTypeRepository mediaTypeRepository, CacheHelper cacheHelper = null) { - mediaTypeRepository = new MediaTypeRepository(unitOfWork, CacheHelper, Mock.Of(), SqlSyntax); - var tagRepository = new TagRepository(unitOfWork, CacheHelper, Mock.Of(), SqlSyntax); - var repository = new MediaRepository(unitOfWork, CacheHelper, Mock.Of(), SqlSyntax, mediaTypeRepository, tagRepository, Mock.Of()); + cacheHelper = cacheHelper ?? CacheHelper; + + mediaTypeRepository = new MediaTypeRepository(unitOfWork, cacheHelper, Mock.Of(), SqlSyntax); + var tagRepository = new TagRepository(unitOfWork, cacheHelper, Mock.Of(), SqlSyntax); + var repository = new MediaRepository(unitOfWork, cacheHelper, Mock.Of(), SqlSyntax, mediaTypeRepository, tagRepository, Mock.Of()); return repository; } + [Test] + public void Cache_Active_By_Int_And_Guid() + { + var provider = new PetaPocoUnitOfWorkProvider(Logger); + var unitOfWork = provider.GetUnitOfWork(); + MediaTypeRepository mediaTypeRepository; + + var realCache = new CacheHelper( + new ObjectCacheRuntimeCacheProvider(), + new StaticCacheProvider(), + new StaticCacheProvider(), + new IsolatedRuntimeCache(t => new ObjectCacheRuntimeCacheProvider())); + + using (var repository = CreateRepository(unitOfWork, out mediaTypeRepository, cacheHelper: realCache)) + { + DatabaseContext.Database.DisableSqlCount(); + + var mediaType = MockedContentTypes.CreateSimpleMediaType("umbTextpage1", "Textpage"); + var media = MockedMedia.CreateSimpleMedia(mediaType, "hello", -1); + mediaTypeRepository.AddOrUpdate(mediaType); + repository.AddOrUpdate(media); + unitOfWork.Commit(); + + DatabaseContext.Database.EnableSqlCount(); + + //go get it, this should already be cached since the default repository key is the INT + var found = repository.Get(media.Id); + Assert.AreEqual(0, DatabaseContext.Database.SqlCount); + //retrieve again, this should use cache + found = repository.Get(media.Id); + Assert.AreEqual(0, DatabaseContext.Database.SqlCount); + + //reset counter + DatabaseContext.Database.DisableSqlCount(); + DatabaseContext.Database.EnableSqlCount(); + + //now get by GUID, this won't be cached yet because the default repo key is not a GUID + found = repository.Get(media.Key); + var sqlCount = DatabaseContext.Database.SqlCount; + Assert.Greater(sqlCount, 0); + //retrieve again, this should use cache now + found = repository.Get(media.Key); + Assert.AreEqual(sqlCount, DatabaseContext.Database.SqlCount); + } + } + [Test] public void Rebuild_All_Xml_Structures() { From d756f884a7622f829a4739b4650f485bfacb06b3 Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 10 Aug 2017 12:02:23 +1000 Subject: [PATCH 7/7] fixes test --- .../Persistence/Repositories/ContentRepositoryTest.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs index 8814ef229e..22331bc850 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs @@ -45,6 +45,8 @@ namespace Umbraco.Tests.Persistence.Repositories private ContentRepository CreateRepository(IScopeUnitOfWork unitOfWork, out ContentTypeRepository contentTypeRepository, out DataTypeDefinitionRepository dtdRepository, CacheHelper cacheHelper = null) { + cacheHelper = cacheHelper ?? CacheHelper; + TemplateRepository tr; var ctRepository = CreateRepository(unitOfWork, out contentTypeRepository, out tr); dtdRepository = new DataTypeDefinitionRepository(unitOfWork, cacheHelper, Logger, SqlSyntax, contentTypeRepository);