diff --git a/src/Umbraco.Core/Models/ReadOnlyRelation.cs b/src/Umbraco.Core/Models/ReadOnlyRelation.cs new file mode 100644 index 0000000000..f2801a93ec --- /dev/null +++ b/src/Umbraco.Core/Models/ReadOnlyRelation.cs @@ -0,0 +1,35 @@ +using System; + +namespace Umbraco.Core.Models +{ + /// + /// A read only relation. Can be used to bulk save witch performs better than the normal save operation, + /// but do not populate Ids back to the model + /// + public class ReadOnlyRelation + { + public ReadOnlyRelation(int id, int parentId, int childId, int relationTypeId, DateTime createDate, string comment) + { + Id = id; + ParentId = parentId; + ChildId = childId; + RelationTypeId = relationTypeId; + CreateDate = createDate; + Comment = comment; + } + + public ReadOnlyRelation(int parentId, int childId, int relationTypeId): this(0, parentId, childId, relationTypeId, DateTime.Now, string.Empty) + { + + } + + public int Id { get; } + public int ParentId { get; } + public int ChildId { get; } + public int RelationTypeId { get; } + public DateTime CreateDate { get; } + public string Comment { get; } + + public bool HasIdentity => Id != 0; + } +} diff --git a/src/Umbraco.Core/Persistence/Repositories/IRelationRepository.cs b/src/Umbraco.Core/Persistence/Repositories/IRelationRepository.cs index fc1be20e6f..ca40848138 100644 --- a/src/Umbraco.Core/Persistence/Repositories/IRelationRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/IRelationRepository.cs @@ -17,6 +17,12 @@ namespace Umbraco.Core.Persistence.Repositories /// void Save(IEnumerable relations); + /// + /// Persist multiple at once but Ids are not returned on created relations + /// + /// + void SaveBulk(IEnumerable relations); + /// /// Deletes all relations for a parent for any specified relation type alias /// diff --git a/src/Umbraco.Infrastructure/Persistence/Factories/RelationFactory.cs b/src/Umbraco.Infrastructure/Persistence/Factories/RelationFactory.cs index d8f100cdbe..f4117cc358 100644 --- a/src/Umbraco.Infrastructure/Persistence/Factories/RelationFactory.cs +++ b/src/Umbraco.Infrastructure/Persistence/Factories/RelationFactory.cs @@ -45,5 +45,22 @@ namespace Umbraco.Core.Persistence.Factories return dto; } + public static RelationDto BuildDto(ReadOnlyRelation entity) + { + var dto = new RelationDto + { + ChildId = entity.ChildId, + Comment = string.IsNullOrEmpty(entity.Comment) ? string.Empty : entity.Comment, + Datetime = entity.CreateDate, + ParentId = entity.ParentId, + RelationType = entity.RelationTypeId + }; + + if (entity.HasIdentity) + dto.Id = entity.Id; + + return dto; + } + } } diff --git a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/ContentRepositoryBase.cs b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/ContentRepositoryBase.cs index b8edbd051a..a0a26ea428 100644 --- a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/ContentRepositoryBase.cs +++ b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/ContentRepositoryBase.cs @@ -980,11 +980,11 @@ namespace Umbraco.Core.Persistence.Repositories.Implement if (!keyToIds.TryGetValue(guid, out var id)) return null; // This shouldn't happen! - return new Relation(entity.Id, id, relationType); + return new ReadOnlyRelation(entity.Id, id, relationType.Id); }).WhereNotNull(); // Save bulk relations - RelationRepository.Save(toSave); + RelationRepository.SaveBulk(toSave); } diff --git a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/RelationRepository.cs b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/RelationRepository.cs index 1f166b9c9e..21b4ce5911 100644 --- a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/RelationRepository.cs +++ b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/RelationRepository.cs @@ -235,16 +235,16 @@ namespace Umbraco.Core.Persistence.Repositories.Implement }, RelationFactory.BuildDto); // value = DTO - // Use NPoco's own InsertBulk command which will automatically re-populate the new Ids on the DTOs, our own - // BulkInsertRecords does not cater for this. - // UPDATE: actually this only seems to work if the database type is SqlServerCEDatabaseType, as this will do - // individual inserts for each record. - // For full SQL and LocalDb, SQL bulk copy is used, and this doesn't update the Ids. - Database.InsertBulk(entitiesAndDtos.Values); - // Re-assign ID to the entity if they've been set on the DTO. + foreach (var dto in entitiesAndDtos.Values) + { + Database.Insert(dto); + } + + // All dtos now have IDs assigned foreach (var de in entitiesAndDtos) { + // re-assign ID to the entity de.Key.Id = de.Value.Id; } @@ -253,6 +253,33 @@ namespace Umbraco.Core.Persistence.Repositories.Implement } } + public void SaveBulk(IEnumerable relations) + { + foreach (var hasIdentityGroup in relations.GroupBy(r => r.HasIdentity)) + { + if (hasIdentityGroup.Key) + { + // Do updates, we can't really do a bulk update so this is still a 1 by 1 operation + // however we can bulk populate the object types. It might be possible to bulk update + // with SQL but would be pretty ugly and we're not really too worried about that for perf, + // it's the bulk inserts we care about. + foreach (var relation in hasIdentityGroup) + { + var dto = RelationFactory.BuildDto(relation); + Database.Update(dto); + } + } + else + { + // Do bulk inserts + var dtos = hasIdentityGroup.Select(RelationFactory.BuildDto); + + Database.InsertBulk(dtos); + + } + } + } + public IEnumerable GetPagedRelationsByQuery(IQuery query, long pageIndex, int pageSize, out long totalRecords, Ordering ordering) { var sql = GetBaseQuery(false); diff --git a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/RelationTypeRepository.cs b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/RelationTypeRepository.cs index bbaebbc9a9..398dd225ba 100644 --- a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/RelationTypeRepository.cs +++ b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/RelationTypeRepository.cs @@ -50,10 +50,6 @@ namespace Umbraco.Core.Persistence.Repositories.Implement { var sql = GetBaseQuery(false); - // should not happen due to the cache policy - if (ids.Any()) - throw new NotImplementedException(); - var dtos = Database.Fetch(sql); return dtos.Select(x => DtoToEntity(x)); diff --git a/src/Umbraco.Tests.Common/Builders/ContentTypeBuilder.cs b/src/Umbraco.Tests.Common/Builders/ContentTypeBuilder.cs index 43b45c68eb..eb4192364f 100644 --- a/src/Umbraco.Tests.Common/Builders/ContentTypeBuilder.cs +++ b/src/Umbraco.Tests.Common/Builders/ContentTypeBuilder.cs @@ -148,10 +148,10 @@ namespace Umbraco.Tests.Common.Builders return (ContentType)builder.Build(); }public static ContentType CreateSimpleContentType(string alias = null, string name = null, IContentType parent = null, bool randomizeAliases = false, string propertyGroupName = "Content", bool mandatoryProperties = false, int defaultTemplateId = 0) { - return (ContentType)CreateSimpleContentTypeHelper(alias, name, parent, randomizeAliases, propertyGroupName, defaultTemplateId).Build(); + return (ContentType)CreateSimpleContentTypeHelper(alias, name, parent, randomizeAliases, propertyGroupName, mandatoryProperties, defaultTemplateId).Build(); } - public static ContentTypeBuilder CreateSimpleContentTypeHelper(string alias = null, string name = null, IContentType parent = null, bool randomizeAliases = false, string propertyGroupName = "Content", int defaultTemplateId = 0) + public static ContentTypeBuilder CreateSimpleContentTypeHelper(string alias = null, string name = null, IContentType parent = null, bool randomizeAliases = false, string propertyGroupName = "Content", bool mandatoryProperties = false, int defaultTemplateId = 0) { return new ContentTypeBuilder() .WithAlias(alias ?? "simple") diff --git a/src/Umbraco.Tests.Common/Builders/MemberBuilder.cs b/src/Umbraco.Tests.Common/Builders/MemberBuilder.cs index fdbc81e895..001956b66e 100644 --- a/src/Umbraco.Tests.Common/Builders/MemberBuilder.cs +++ b/src/Umbraco.Tests.Common/Builders/MemberBuilder.cs @@ -178,6 +178,33 @@ namespace Umbraco.Tests.Common.Builders return member; } + public static IEnumerable CreateSimpleMembers(IMemberType memberType, int amount, Action onCreating = null) + { + var list = new List(); + + for (int i = 0; i < amount; i++) + { + var name = "Member No-" + i; + + var builder = new MemberBuilder() + .WithMemberType(memberType) + .WithName(name) + .WithEmail("test" + i + "@test.com") + .WithLogin("test" + i, "test" + i); + + + builder = builder + .AddPropertyData() + .WithKeyValue("title", name + " member" + i) + .WithKeyValue("bodyText", "This is a subpage" + i) + .WithKeyValue("author", "John Doe" + i) + .Done(); + + list.Add(builder.Build()); + } + + return list; + } public static Member CreateSimpleMember(IMemberType memberType, string name, string email, string password, string username, Guid? key = null) { var builder = new MemberBuilder() diff --git a/src/Umbraco.Tests/Persistence/Repositories/RelationRepositoryTest.cs b/src/Umbraco.Tests.Integration/Persistence/Repositories/RelationRepositoryTest.cs similarity index 60% rename from src/Umbraco.Tests/Persistence/Repositories/RelationRepositoryTest.cs rename to src/Umbraco.Tests.Integration/Persistence/Repositories/RelationRepositoryTest.cs index 9cdd0d7c4a..63e4ada345 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/RelationRepositoryTest.cs +++ b/src/Umbraco.Tests.Integration/Persistence/Repositories/RelationRepositoryTest.cs @@ -12,6 +12,9 @@ using Umbraco.Core.Persistence.Dtos; using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.Repositories.Implement; using Umbraco.Core.Scoping; +using Umbraco.Core.Services; +using Umbraco.Tests.Common.Builders; +using Umbraco.Tests.Integration.Testing; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.TestHelpers.Entities; using Umbraco.Tests.Testing; @@ -20,37 +23,51 @@ namespace Umbraco.Tests.Persistence.Repositories { [TestFixture] [UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest)] - public class RelationRepositoryTest : TestWithDatabaseBase + public class RelationRepositoryTest : UmbracoIntegrationTest { - public override void SetUp() - { - base.SetUp(); + private RelationType _relateContent; + private RelationType _relateContentType; + private ContentType _contentType; + private Content _textpage; + private Content _subpage; + private Content _subpage2; + private Relation _relation; + private Relation _relation2; + private IContentTypeService ContentTypeService => GetRequiredService(); + private IContentService ContentService => GetRequiredService(); + private IMediaTypeService MediaTypeService => GetRequiredService(); + private IMediaService MediaService => GetRequiredService(); + + private IMemberTypeService MemberTypeService => GetRequiredService(); + private IMemberService MemberService => GetRequiredService(); + private IRelationService RelationService => GetRequiredService(); + private IFileService FileService => GetRequiredService(); + + [SetUp] + public void SetUp() + { CreateTestData(); } private RelationRepository CreateRepository(IScopeProvider provider, out RelationTypeRepository relationTypeRepository) { - var accessor = (IScopeAccessor) provider; - relationTypeRepository = new RelationTypeRepository(accessor, AppCaches.Disabled, Mock.Of>()); - var entityRepository = new EntityRepository(accessor); - var repository = new RelationRepository(accessor, Mock.Of>(), relationTypeRepository, entityRepository); - return repository; + relationTypeRepository = (RelationTypeRepository)GetRequiredService(); + return (RelationRepository)GetRequiredService(); } [Test] public void Can_Perform_Add_On_RelationRepository() { // Arrange - var provider = TestObjects.GetScopeProvider(LoggerFactory); - using (var scope = provider.CreateScope()) + using (var scope = ScopeProvider.CreateScope()) { RelationTypeRepository repositoryType; - var repository = CreateRepository(provider, out repositoryType); + var repository = CreateRepository(ScopeProvider, out repositoryType); // Act var relationType = repositoryType.Get(1); - var relation = new Relation(NodeDto.NodeIdSeed + 2, NodeDto.NodeIdSeed + 3, relationType); + var relation = new Relation(_textpage.Id, _subpage.Id, relationType); repository.Save(relation); @@ -64,11 +81,10 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Update_On_RelationRepository() { // Arrange - var provider = TestObjects.GetScopeProvider(LoggerFactory); - using (var scope = provider.CreateScope()) + using (var scope = ScopeProvider.CreateScope()) { RelationTypeRepository repositoryType; - var repository = CreateRepository(provider, out repositoryType); + var repository = CreateRepository(ScopeProvider, out repositoryType); // Act var relation = repository.Get(1); @@ -89,11 +105,10 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Delete_On_RelationRepository() { // Arrange - var provider = TestObjects.GetScopeProvider(LoggerFactory); - using (var scope = provider.CreateScope()) + using (var scope = ScopeProvider.CreateScope()) { RelationTypeRepository repositoryType; - var repository = CreateRepository(provider, out repositoryType); + var repository = CreateRepository(ScopeProvider, out repositoryType); // Act var relation = repository.Get(2); @@ -111,11 +126,10 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Get_On_RelationRepository() { // Arrange - var provider = TestObjects.GetScopeProvider(LoggerFactory); - using (var scope = provider.CreateScope()) + using (var scope = ScopeProvider.CreateScope()) { RelationTypeRepository repositoryType; - var repository = CreateRepository(provider, out repositoryType); + var repository = CreateRepository(ScopeProvider, out repositoryType); // Act var relation = repository.Get(1); @@ -123,8 +137,8 @@ namespace Umbraco.Tests.Persistence.Repositories // Assert Assert.That(relation, Is.Not.Null); Assert.That(relation.HasIdentity, Is.True); - Assert.That(relation.ChildId, Is.EqualTo(NodeDto.NodeIdSeed + 3)); - Assert.That(relation.ParentId, Is.EqualTo(NodeDto.NodeIdSeed + 2)); + Assert.That(relation.ChildId, Is.EqualTo(_subpage.Id)); + Assert.That(relation.ParentId, Is.EqualTo(_textpage.Id)); Assert.That(relation.RelationType.Alias, Is.EqualTo("relateContentOnCopy")); } } @@ -133,11 +147,10 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetAll_On_RelationRepository() { // Arrange - var provider = TestObjects.GetScopeProvider(LoggerFactory); - using (var scope = provider.CreateScope()) + using (var scope = ScopeProvider.CreateScope()) { RelationTypeRepository repositoryType; - var repository = CreateRepository(provider, out repositoryType); + var repository = CreateRepository(ScopeProvider, out repositoryType); // Act var relations = repository.GetMany(); @@ -154,11 +167,10 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetAll_With_Params_On_RelationRepository() { // Arrange - var provider = TestObjects.GetScopeProvider(LoggerFactory); - using (var scope = provider.CreateScope()) + using (var scope = ScopeProvider.CreateScope()) { RelationTypeRepository repositoryType; - var repository = CreateRepository(provider, out repositoryType); + var repository = CreateRepository(ScopeProvider, out repositoryType); // Act var relations = repository.GetMany(1, 2); @@ -176,35 +188,34 @@ namespace Umbraco.Tests.Persistence.Repositories { CreateTestDataForPagingTests(out var createdContent, out var createdMembers, out var createdMedia); - var provider = TestObjects.GetScopeProvider(LoggerFactory); - using (var scope = provider.CreateScope()) + using (var scope = ScopeProvider.CreateScope()) { - var repository = CreateRepository(provider, out var relationTypeRepository); + var repository = CreateRepository(ScopeProvider, out var relationTypeRepository); // Get parent entities for child id var parents = repository.GetPagedParentEntitiesByChildId(createdMedia[0].Id, 0, 11, out var totalRecords).ToList(); - Assert.AreEqual(20, totalRecords); - Assert.AreEqual(11, parents.Count); + Assert.AreEqual(6, totalRecords); + Assert.AreEqual(6, parents.Count); //add the next page parents.AddRange(repository.GetPagedParentEntitiesByChildId(createdMedia[0].Id, 1, 11, out totalRecords)); - Assert.AreEqual(20, totalRecords); - Assert.AreEqual(20, parents.Count); + Assert.AreEqual(6, totalRecords); + Assert.AreEqual(6, parents.Count); var contentEntities = parents.OfType().ToList(); var mediaEntities = parents.OfType().ToList(); var memberEntities = parents.OfType().ToList(); - Assert.AreEqual(10, contentEntities.Count); + Assert.AreEqual(3, contentEntities.Count); Assert.AreEqual(0, mediaEntities.Count); - Assert.AreEqual(10, memberEntities.Count); + Assert.AreEqual(3, memberEntities.Count); //only of a certain type parents.AddRange(repository.GetPagedParentEntitiesByChildId(createdMedia[0].Id, 0, 100, out totalRecords, UmbracoObjectTypes.Document.GetGuid())); - Assert.AreEqual(10, totalRecords); + Assert.AreEqual(3, totalRecords); parents.AddRange(repository.GetPagedParentEntitiesByChildId(createdMedia[0].Id, 0, 100, out totalRecords, UmbracoObjectTypes.Member.GetGuid())); - Assert.AreEqual(10, totalRecords); + Assert.AreEqual(3, totalRecords); parents.AddRange(repository.GetPagedParentEntitiesByChildId(createdMedia[0].Id, 0, 100, out totalRecords, UmbracoObjectTypes.Media.GetGuid())); Assert.AreEqual(0, totalRecords); @@ -215,17 +226,16 @@ namespace Umbraco.Tests.Persistence.Repositories public void Get_Paged_Parent_Child_Entities_With_Same_Entity_Relation() { //Create a media item and create a relationship between itself (parent -> child) - var imageType = MockedContentTypes.CreateImageMediaType("myImage"); - ServiceContext.MediaTypeService.Save(imageType); - var media = MockedMedia.CreateMediaImage(imageType, -1); - ServiceContext.MediaService.Save(media); - var relType = ServiceContext.RelationService.GetRelationTypeByAlias(Constants.Conventions.RelationTypes.RelatedMediaAlias); - ServiceContext.RelationService.Relate(media.Id, media.Id, relType); + var imageType = MediaTypeBuilder.CreateImageMediaType("myImage"); + MediaTypeService.Save(imageType); + var media = MediaBuilder.CreateMediaImage(imageType, -1); + MediaService.Save(media); + var relType = RelationService.GetRelationTypeByAlias(Constants.Conventions.RelationTypes.RelatedMediaAlias); + RelationService.Relate(media.Id, media.Id, relType); - var provider = TestObjects.GetScopeProvider(LoggerFactory); - using (var scope = provider.CreateScope()) + using (var scope = ScopeProvider.CreateScope()) { - var repository = CreateRepository(provider, out var relationTypeRepository); + var repository = CreateRepository(ScopeProvider, out var relationTypeRepository); // Get parent entities for child id var parents = repository.GetPagedParentEntitiesByChildId(media.Id, 0, 10, out var totalRecords).ToList(); @@ -244,35 +254,34 @@ namespace Umbraco.Tests.Persistence.Repositories { CreateTestDataForPagingTests(out var createdContent, out var createdMembers, out var createdMedia); - var provider = TestObjects.GetScopeProvider(LoggerFactory); - using (var scope = provider.CreateScope()) + using (var scope = ScopeProvider.CreateScope()) { - var repository = CreateRepository(provider, out var relationTypeRepository); + var repository = CreateRepository(ScopeProvider, out var relationTypeRepository); // Get parent entities for child id var parents = repository.GetPagedChildEntitiesByParentId(createdContent[0].Id, 0, 6, out var totalRecords).ToList(); - Assert.AreEqual(10, totalRecords); - Assert.AreEqual(6, parents.Count); + Assert.AreEqual(3, totalRecords); + Assert.AreEqual(3, parents.Count); //add the next page parents.AddRange(repository.GetPagedChildEntitiesByParentId(createdContent[0].Id, 1, 6, out totalRecords)); - Assert.AreEqual(10, totalRecords); - Assert.AreEqual(10, parents.Count); + Assert.AreEqual(3, totalRecords); + Assert.AreEqual(3, parents.Count); var contentEntities = parents.OfType().ToList(); var mediaEntities = parents.OfType().ToList(); var memberEntities = parents.OfType().ToList(); Assert.AreEqual(0, contentEntities.Count); - Assert.AreEqual(10, mediaEntities.Count); + Assert.AreEqual(3, mediaEntities.Count); Assert.AreEqual(0, memberEntities.Count); //only of a certain type parents.AddRange(repository.GetPagedChildEntitiesByParentId(createdContent[0].Id, 0, 100, out totalRecords, UmbracoObjectTypes.Media.GetGuid())); - Assert.AreEqual(10, totalRecords); + Assert.AreEqual(3, totalRecords); parents.AddRange(repository.GetPagedChildEntitiesByParentId(createdMembers[0].Id, 0, 100, out totalRecords, UmbracoObjectTypes.Media.GetGuid())); - Assert.AreEqual(10, totalRecords); + Assert.AreEqual(3, totalRecords); parents.AddRange(repository.GetPagedChildEntitiesByParentId(createdContent[0].Id, 0, 100, out totalRecords, UmbracoObjectTypes.Member.GetGuid())); Assert.AreEqual(0, totalRecords); @@ -283,53 +292,52 @@ namespace Umbraco.Tests.Persistence.Repositories { //Create content createdContent = new List(); - var contentType = MockedContentTypes.CreateBasicContentType("blah"); - ServiceContext.ContentTypeService.Save(contentType); - for (int i = 0; i < 10; i++) + var contentType = ContentTypeBuilder.CreateBasicContentType("blah"); + ContentTypeService.Save(contentType); + for (int i = 0; i < 3; i++) { - var c1 = MockedContent.CreateBasicContent(contentType); - ServiceContext.ContentService.Save(c1); + var c1 = ContentBuilder.CreateBasicContent(contentType); + ContentService.Save(c1); createdContent.Add(c1); } //Create media createdMedia = new List(); - var imageType = MockedContentTypes.CreateImageMediaType("myImage"); - ServiceContext.MediaTypeService.Save(imageType); - for (int i = 0; i < 10; i++) + var imageType = MediaTypeBuilder.CreateImageMediaType("myImage"); + MediaTypeService.Save(imageType); + for (int i = 0; i < 3; i++) { - var c1 = MockedMedia.CreateMediaImage(imageType, -1); - ServiceContext.MediaService.Save(c1); + var c1 = MediaBuilder.CreateMediaImage(imageType, -1); + MediaService.Save(c1); createdMedia.Add(c1); } // Create members - var memberType = MockedContentTypes.CreateSimpleMemberType("simple"); - ServiceContext.MemberTypeService.Save(memberType); - createdMembers = MockedMember.CreateSimpleMember(memberType, 10).ToList(); - ServiceContext.MemberService.Save(createdMembers); + var memberType = MemberTypeBuilder.CreateSimpleMemberType("simple"); + MemberTypeService.Save(memberType); + createdMembers = MemberBuilder.CreateSimpleMembers(memberType, 3).ToList(); + MemberService.Save(createdMembers); - var relType = ServiceContext.RelationService.GetRelationTypeByAlias(Constants.Conventions.RelationTypes.RelatedMediaAlias); + var relType = RelationService.GetRelationTypeByAlias(Constants.Conventions.RelationTypes.RelatedMediaAlias); // Relate content to media foreach (var content in createdContent) foreach (var media in createdMedia) - ServiceContext.RelationService.Relate(content.Id, media.Id, relType); + RelationService.Relate(content.Id, media.Id, relType); // Relate members to media foreach (var member in createdMembers) foreach (var media in createdMedia) - ServiceContext.RelationService.Relate(member.Id, media.Id, relType); + RelationService.Relate(member.Id, media.Id, relType); } [Test] public void Can_Perform_Exists_On_RelationRepository() { // Arrange - var provider = TestObjects.GetScopeProvider(LoggerFactory); - using (var scope = provider.CreateScope()) + using (var scope = ScopeProvider.CreateScope()) { RelationTypeRepository repositoryType; - var repository = CreateRepository(provider, out repositoryType); + var repository = CreateRepository(ScopeProvider, out repositoryType); // Act var exists = repository.Exists(2); @@ -345,14 +353,13 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Count_On_RelationRepository() { // Arrange - var provider = TestObjects.GetScopeProvider(LoggerFactory); - using (var scope = provider.CreateScope()) + using (var scope = ScopeProvider.CreateScope()) { RelationTypeRepository repositoryType; - var repository = CreateRepository(provider, out repositoryType); + var repository = CreateRepository(ScopeProvider, out repositoryType); // Act - var query = scope.SqlContext.Query().Where(x => x.ParentId == NodeDto.NodeIdSeed + 2); + var query = scope.SqlContext.Query().Where(x => x.ParentId == _textpage.Id); int count = repository.Count(query); // Assert @@ -364,14 +371,13 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetByQuery_On_RelationRepository() { // Arrange - var provider = TestObjects.GetScopeProvider(LoggerFactory); - using (var scope = provider.CreateScope()) + using (var scope = ScopeProvider.CreateScope()) { RelationTypeRepository repositoryType; - var repository = CreateRepository(provider, out repositoryType); + var repository = CreateRepository(ScopeProvider, out repositoryType); // Act - var query = scope.SqlContext.Query().Where(x => x.RelationTypeId == RelationTypeDto.NodeIdSeed); + var query = scope.SqlContext.Query().Where(x => x.RelationTypeId == _relateContent.Id); var relations = repository.Get(query); // Assert @@ -386,14 +392,13 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Delete_Content_And_Verify_Relation_Is_Removed() { // Arrange - var provider = TestObjects.GetScopeProvider(LoggerFactory); - using (var scope = provider.CreateScope()) + using (var scope = ScopeProvider.CreateScope()) { RelationTypeRepository repositoryType; - var repository = CreateRepository(provider, out repositoryType); + var repository = CreateRepository(ScopeProvider, out repositoryType); - var content = ServiceContext.ContentService.GetById(NodeDto.NodeIdSeed + 3); - ServiceContext.ContentService.Delete(content, 0); + var content = ContentService.GetById(_subpage.Id); + ContentService.Delete(content, 0); // Act var shouldntExist = repository.Exists(1); @@ -413,49 +418,50 @@ namespace Umbraco.Tests.Persistence.Repositories public void CreateTestData() { - var relateContent = new RelationType( + _relateContent = new RelationType( "Relate Content on Copy", "relateContentOnCopy", true, Constants.ObjectTypes.Document, new Guid("C66BA18E-EAF3-4CFF-8A22-41B16D66A972")); - var relateContentType = new RelationType("Relate ContentType on Copy", + _relateContentType = new RelationType("Relate ContentType on Copy", "relateContentTypeOnCopy", true, Constants.ObjectTypes.DocumentType, new Guid("A2CB7800-F571-4787-9638-BC48539A0EFB")); - var provider = TestObjects.GetScopeProvider(LoggerFactory); - using (var scope = provider.CreateScope()) + using (var scope = ScopeProvider.CreateScope()) { - var accessor = (IScopeAccessor)provider; + var accessor = (IScopeAccessor)ScopeProvider; var relationTypeRepository = new RelationTypeRepository(accessor, AppCaches.Disabled, Mock.Of>()); var entityRepository = new EntityRepository(accessor); var relationRepository = new RelationRepository(accessor, Mock.Of>(), relationTypeRepository, entityRepository); - relationTypeRepository.Save(relateContent); - relationTypeRepository.Save(relateContentType); + relationTypeRepository.Save(_relateContent); + relationTypeRepository.Save(_relateContentType); + var template = TemplateBuilder.CreateTextPageTemplate(); + FileService.SaveTemplate(template); //Create and Save ContentType "umbTextpage" -> (NodeDto.NodeIdSeed) - ContentType contentType = MockedContentTypes.CreateSimpleContentType("umbTextpage", "Textpage"); - ServiceContext.FileService.SaveTemplate(contentType.DefaultTemplate); // else, FK violation on contentType! - ServiceContext.ContentTypeService.Save(contentType); + _contentType = ContentTypeBuilder.CreateSimpleContentType("umbTextpage", "Textpage", defaultTemplateId: template.Id); + + ContentTypeService.Save(_contentType); //Create and Save Content "Homepage" based on "umbTextpage" -> (NodeDto.NodeIdSeed + 1) - Content textpage = MockedContent.CreateSimpleContent(contentType); - ServiceContext.ContentService.Save(textpage, 0); + _textpage = ContentBuilder.CreateSimpleContent(_contentType); + ContentService.Save(_textpage, 0); //Create and Save Content "Text Page 1" based on "umbTextpage" -> (NodeDto.NodeIdSeed + 2) - Content subpage = MockedContent.CreateSimpleContent(contentType, "Text Page 1", textpage.Id); - ServiceContext.ContentService.Save(subpage, 0); + _subpage = ContentBuilder.CreateSimpleContent(_contentType, "Text Page 1", _textpage.Id); + ContentService.Save(_subpage, 0); //Create and Save Content "Text Page 1" based on "umbTextpage" -> (NodeDto.NodeIdSeed + 3) - Content subpage2 = MockedContent.CreateSimpleContent(contentType, "Text Page 2", textpage.Id); - ServiceContext.ContentService.Save(subpage2, 0); + _subpage2 = ContentBuilder.CreateSimpleContent(_contentType, "Text Page 2", _textpage.Id); + ContentService.Save(_subpage2, 0); - var relation = new Relation(textpage.Id, subpage.Id, relateContent) { Comment = string.Empty }; - var relation2 = new Relation(textpage.Id, subpage2.Id, relateContent) { Comment = string.Empty }; - relationRepository.Save(relation); - relationRepository.Save(relation2); + _relation = new Relation(_textpage.Id, _subpage.Id, _relateContent) { Comment = string.Empty }; + _relation2 = new Relation(_textpage.Id, _subpage2.Id, _relateContent) { Comment = string.Empty }; + relationRepository.Save(_relation); + relationRepository.Save(_relation2); scope.Complete(); } } diff --git a/src/Umbraco.Tests.Integration/Services/RelationServiceTests.cs b/src/Umbraco.Tests.Integration/Services/RelationServiceTests.cs index 94252433fb..9fe4867fc2 100644 --- a/src/Umbraco.Tests.Integration/Services/RelationServiceTests.cs +++ b/src/Umbraco.Tests.Integration/Services/RelationServiceTests.cs @@ -6,12 +6,14 @@ using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Models; using Umbraco.Core.Services; +using Umbraco.Core.Services.Implement; using Umbraco.Tests.Common.Builders; -using Umbraco.Tests.Common.Builders.Extensions; using Umbraco.Tests.Integration.Testing; +using Umbraco.Tests.TestHelpers; +using Umbraco.Tests.TestHelpers.Entities; using Umbraco.Tests.Testing; -namespace Umbraco.Tests.Integration.Services +namespace Umbraco.Tests.Services { [TestFixture] [Apartment(ApartmentState.STA)] @@ -19,30 +21,30 @@ namespace Umbraco.Tests.Integration.Services public class RelationServiceTests : UmbracoIntegrationTest { private IContentTypeService ContentTypeService => GetRequiredService(); - private IMediaTypeService MediaTypeService => GetRequiredService(); private IContentService ContentService => GetRequiredService(); + private IMediaTypeService MediaTypeService => GetRequiredService(); private IMediaService MediaService => GetRequiredService(); private IRelationService RelationService => GetRequiredService(); [Test] public void Get_Paged_Relations_By_Relation_Type() { - // Create content + //Create content var createdContent = new List(); var contentType = ContentTypeBuilder.CreateBasicContentType("blah"); ContentTypeService.Save(contentType); - for (var i = 0; i < 10; i++) + for (int i = 0; i < 3; i++) { var c1 = ContentBuilder.CreateBasicContent(contentType); ContentService.Save(c1); createdContent.Add(c1); } - // Create media + //Create media var createdMedia = new List(); var imageType = MediaTypeBuilder.CreateImageMediaType("myImage"); MediaTypeService.Save(imageType); - for (var i = 0; i < 10; i++) + for (int i = 0; i < 3; i++) { var c1 = MediaBuilder.CreateMediaImage(imageType, -1); MediaService.Save(c1); @@ -56,16 +58,16 @@ namespace Umbraco.Tests.Integration.Services foreach (var media in createdMedia) RelationService.Relate(content.Id, media.Id, relType); - var paged = RelationService.GetPagedByRelationTypeId(relType.Id, 0, 51, out var totalRecs).ToList(); + var paged = RelationService.GetPagedByRelationTypeId(relType.Id, 0, 4, out var totalRecs).ToList(); - Assert.AreEqual(100, totalRecs); - Assert.AreEqual(51, paged.Count); + Assert.AreEqual(9, totalRecs); + Assert.AreEqual(4, paged.Count); - // Next page - paged.AddRange(RelationService.GetPagedByRelationTypeId(relType.Id, 1, 51, out totalRecs)); + //next page + paged.AddRange(RelationService.GetPagedByRelationTypeId(relType.Id, 1, 4, out totalRecs)); - Assert.AreEqual(100, totalRecs); - Assert.AreEqual(100, paged.Count); + Assert.AreEqual(9, totalRecs); + Assert.AreEqual(8, paged.Count); Assert.IsTrue(createdContent.Select(x => x.Id).ContainsAll(paged.Select(x => x.ParentId))); Assert.IsTrue(createdMedia.Select(x => x.Id).ContainsAll(paged.Select(x => x.ChildId))); @@ -107,12 +109,7 @@ namespace Umbraco.Tests.Integration.Services public void Can_Create_RelationType_Without_Name() { var rs = RelationService; - var rt = new RelationTypeBuilder() - .WithName("Test") - .WithAlias("repeatedEventOccurence") - .WithParentObjectType(Constants.ObjectTypes.Document) - .WithChildObjectType(Constants.ObjectTypes.Media) - .Build(); + IRelationType rt = new RelationType("Test", "repeatedEventOccurence", false, Constants.ObjectTypes.Document, Constants.ObjectTypes.Media); Assert.DoesNotThrow(() => rs.Save(rt)); @@ -130,10 +127,7 @@ namespace Umbraco.Tests.Integration.Services public void Create_Relation_Type_Without_Object_Types() { var rs = RelationService; - var rt = new RelationTypeBuilder() - .WithName("repeatedEventOccurence") - .WithAlias("repeatedEventOccurence") - .Build(); + IRelationType rt = new RelationType("repeatedEventOccurence", "repeatedEventOccurence", false, null, null); Assert.DoesNotThrow(() => rs.Save(rt)); @@ -170,53 +164,45 @@ namespace Umbraco.Tests.Integration.Services { var rs = RelationService; - var relations = CreateRelations(10); + var newRelations = CreateRelations(10); - Assert.IsTrue(relations.All(x => !x.HasIdentity)); + Assert.IsTrue(newRelations.All(x => !x.HasIdentity)); - RelationService.Save(relations); + RelationService.Save(newRelations); - var insertedRelations = RelationService.GetAllRelations(); - - Assert.AreEqual(10, insertedRelations.Count()); + Assert.IsTrue(newRelations.All(x => x.HasIdentity)); } [Test] public void Update_Bulk_Relations() { + var rs = RelationService; + var date = DateTime.Now.AddDays(-10); - var relations = CreateRelations(10); - foreach (var r in relations) + var newRelations = CreateRelations(10); + foreach (var r in newRelations) { r.CreateDate = date; r.UpdateDate = date; } - // Insert - RelationService.Save(relations); - Assert.IsTrue(relations.All(x => x.UpdateDate == date)); + //insert + RelationService.Save(newRelations); + Assert.IsTrue(newRelations.All(x => x.UpdateDate == date)); - // Re-get the relations to ensure we have updated IDs. - relations = RelationService.GetAllRelations(); - - // Update var newDate = DateTime.Now.AddDays(-5); - foreach (var r in relations) - { + foreach (var r in newRelations) r.UpdateDate = newDate; - } - RelationService.Save(relations); - Assert.IsTrue(relations.All(x => x.UpdateDate == newDate)); + //update + RelationService.Save(newRelations); + Assert.IsTrue(newRelations.All(x => x.UpdateDate == newDate)); } private IRelation CreateAndSaveRelation(string name, string alias) { var rs = RelationService; - var rt = new RelationTypeBuilder() - .WithName(name) - .WithAlias(alias) - .Build(); + var rt = new RelationType(name, alias, false, null, null); rs.Save(rt); var ct = ContentTypeBuilder.CreateBasicContentType(); @@ -230,10 +216,7 @@ namespace Umbraco.Tests.Integration.Services ContentService.Save(c1); MediaService.Save(c2); - var r = new RelationBuilder() - .BetweenIds(c1.Id, c2.Id) - .WithRelationType(rt) - .Build(); + var r = new Relation(c1.Id, c2.Id, rt); RelationService.Save(r); return r; @@ -248,7 +231,7 @@ namespace Umbraco.Tests.Integration.Services { var rs = RelationService; var rtName = Guid.NewGuid().ToString(); - var rt = new RelationTypeBuilder().Build(); + var rt = new RelationType(rtName, rtName, false, null, null); rs.Save(rt); var ct = ContentTypeBuilder.CreateBasicContentType(); @@ -264,10 +247,7 @@ namespace Umbraco.Tests.Integration.Services ContentService.Save(c1); MediaService.Save(c2); - return new RelationBuilder() - .BetweenIds(c1.Id, c2.Id) - .WithRelationType(rt) - .Build(); + return new Relation(c1.Id, c2.Id, rt); }).ToList(); } diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj index 55007b16fb..fbc7a486e2 100644 --- a/src/Umbraco.Tests/Umbraco.Tests.csproj +++ b/src/Umbraco.Tests/Umbraco.Tests.csproj @@ -306,7 +306,6 @@ -