From 6d4644c118276aa9845ccd7e4e018456b5da87fd Mon Sep 17 00:00:00 2001 From: Stephan Date: Tue, 12 Dec 2017 15:04:13 +0100 Subject: [PATCH] UnitOfWork RIP --- .../Repositories/Implement/AuditRepository.cs | 6 +- .../Implement/ContentRepositoryBase.cs | 47 +- .../Implement/ContentTypeRepository.cs | 6 +- .../Implement/ContentTypeRepositoryBase.cs | 5 +- .../Implement/DataTypeContainerRepository.cs | 6 +- .../Implement/DataTypeDefinitionRepository.cs | 11 +- .../Implement/DictionaryRepository.cs | 19 +- .../Implement/DocumentBlueprintRepository.cs | 5 +- .../Implement/DocumentRepository.cs | 24 +- .../DocumentTypeContainerRepository.cs | 6 +- .../Implement/DomainRepository.cs | 8 +- .../Implement/EntityContainerRepository.cs | 5 +- .../Implement/ExternalLoginRepository.cs | 8 +- .../Implement/LanguageRepository.cs | 7 +- .../Repositories/Implement/MacroRepository.cs | 6 +- .../Repositories/Implement/MediaRepository.cs | 21 +- .../Implement/MediaTypeContainerRepository.cs | 6 +- .../Implement/MediaTypeRepository.cs | 7 +- .../Implement/MemberGroupRepository.cs | 14 +- .../Implement/MemberRepository.cs | 15 +- .../Implement/MemberTypeRepository.cs | 8 +- .../Implement/MigrationEntryRepository.cs | 9 +- .../Implement/NPocoRepositoryBase.cs | 19 +- .../Implement/PermissionRepository.cs | 21 +- .../Implement/PublicAccessRepository.cs | 6 +- .../Implement/RedirectUrlRepository.cs | 6 +- .../Implement/RelationRepository.cs | 5 +- .../Implement/RelationTypeRepository.cs | 6 +- .../Implement/RepositoryBaseOfTIdTEntity.cs | 34 +- .../Implement/ServerRegistrationRepository.cs | 6 +- .../Implement/SimpleGetRepository.cs | 26 +- .../Repositories/Implement/TagRepository.cs | 6 +- .../Repositories/Implement/TaskRepository.cs | 12 +- .../Implement/TaskTypeRepository.cs | 9 +- .../Implement/TemplateRepository.cs | 6 +- .../Implement/UserGroupRepository.cs | 13 +- .../Repositories/Implement/UserRepository.cs | 9 +- .../Persistence/UnitOfWorkExtensions.cs | 13 - src/Umbraco.Core/Scoping/IScopeProvider.cs | 3 +- src/Umbraco.Core/Scoping/ScopeProvider.cs | 3 +- src/Umbraco.Core/Services/AuditService.cs | 50 +- src/Umbraco.Core/Services/ContentService.cs | 755 ++++++++---------- .../Services/ContentTypeService.cs | 29 +- .../Services/ContentTypeServiceBase.cs | 4 +- .../ContentTypeServiceBaseOfTItemTService.cs | 64 +- ...peServiceBaseOfTRepositoryTItemTService.cs | 348 ++++---- src/Umbraco.Core/Services/DataTypeService.cs | 237 +++--- src/Umbraco.Core/Services/DomainService.cs | 65 +- src/Umbraco.Core/Services/EntityService.cs | 171 ++-- .../Services/ExternalLoginService.cs | 41 +- src/Umbraco.Core/Services/FileService.cs | 508 ++++++------ src/Umbraco.Core/Services/IdkMap.cs | 52 +- .../Services/LocalizationService.cs | 162 ++-- src/Umbraco.Core/Services/MacroService.cs | 74 +- src/Umbraco.Core/Services/MediaService.cs | 551 ++++++------- src/Umbraco.Core/Services/MediaTypeService.cs | 8 +- .../Services/MemberGroupService.cs | 49 +- src/Umbraco.Core/Services/MemberService.cs | 482 +++++------ .../Services/MemberTypeService.cs | 17 +- .../Services/MigrationEntryService.cs | 28 +- .../Services/NotificationService.cs | 59 +- src/Umbraco.Core/Services/PackagingService.cs | 37 +- .../Services/PublicAccessService.cs | 86 +- .../Services/RedirectUrlService.cs | 68 +- src/Umbraco.Core/Services/RelationService.cs | 200 +++-- .../Services/RepositoryService.cs | 10 +- .../Services/ScopeRepositoryService.cs | 11 +- .../Services/ServerRegistrationService.cs | 73 +- src/Umbraco.Core/Services/TagService.cs | 87 +- src/Umbraco.Core/Services/TaskService.cs | 63 +- src/Umbraco.Core/Services/UserService.cs | 313 ++++---- .../Integration/ContentEventsTests.cs | 18 +- .../Repositories/AuditRepositoryTest.cs | 9 +- .../RedirectUrlRepositoryTests.cs | 22 +- .../Persistence/UnitOfWorkTests.cs | 16 +- .../Services/ContentServiceTests.cs | 6 +- .../Services/MediaServiceTests.cs | 2 +- .../Services/MemberServiceTests.cs | 2 +- .../NuCache/DataSource/Database.cs | 61 +- .../NuCache/PublishedSnapshotService.cs | 299 ++++--- .../XmlPublishedCache/XmlStore.cs | 279 ++++--- src/Umbraco.Web/Services/SectionService.cs | 13 +- 82 files changed, 2751 insertions(+), 3130 deletions(-) diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/AuditRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/AuditRepository.cs index 8535245a6e..4e6dc34d32 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/AuditRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/AuditRepository.cs @@ -9,14 +9,14 @@ using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence.Querying; -using Umbraco.Core.Persistence.UnitOfWork; +using Umbraco.Core.Scoping; namespace Umbraco.Core.Persistence.Repositories.Implement { internal class AuditRepository : NPocoRepositoryBase, IAuditRepository { - public AuditRepository(IScopeUnitOfWork work, [Inject(RepositoryCompositionRoot.DisabledCache)] CacheHelper cache, ILogger logger) - : base(work, cache, logger) + public AuditRepository(ScopeProvider scopeProvider, [Inject(RepositoryCompositionRoot.DisabledCache)] CacheHelper cache, ILogger logger) + : base(scopeProvider, cache, logger) { } protected override void PersistNewItem(AuditItem entity) diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/ContentRepositoryBase.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/ContentRepositoryBase.cs index 7b852e2c7b..a2ff2eb087 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/ContentRepositoryBase.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/ContentRepositoryBase.cs @@ -16,6 +16,7 @@ using Umbraco.Core.Persistence.Factories; using Umbraco.Core.Persistence.Querying; using Umbraco.Core.Persistence.UnitOfWork; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Scoping; using Umbraco.Core.Services; namespace Umbraco.Core.Persistence.Repositories.Implement @@ -32,8 +33,8 @@ namespace Umbraco.Core.Persistence.Repositories.Implement where TEntity : class, IUmbracoEntity where TRepository : class, IRepository { - protected ContentRepositoryBase(IScopeUnitOfWork work, CacheHelper cache, ILogger logger) - : base(work, cache, logger) + protected ContentRepositoryBase(ScopeProvider scopeProvider, CacheHelper cache, ILogger logger) + : base(scopeProvider, cache, logger) { } protected abstract TRepository This { get; } @@ -233,7 +234,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement // orderBy: the name of an ordering field // orderDirection: direction for orderBy // orderBySystemField: whether orderBy is a system field or a custom field (property value) - private Sql PrepareSqlForPagedResults(Sql sql, Sql filterSql, string orderBy, Direction orderDirection, bool orderBySystemField) + private Sql PrepareSqlForPage(Sql sql, Sql filterSql, string orderBy, Direction orderDirection, bool orderBySystemField) { if (filterSql == null && string.IsNullOrEmpty(orderBy)) return sql; @@ -352,7 +353,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement return "customPropData.customPropVal"; } - protected IEnumerable GetPagedResultsByQuery(IQuery query, + protected IEnumerable GetPage(IQuery query, long pageIndex, int pageSize, out long totalRecords, Func, IEnumerable> mapDtos, string orderBy, Direction orderDirection, bool orderBySystemField, @@ -361,11 +362,11 @@ namespace Umbraco.Core.Persistence.Repositories.Implement if (orderBy == null) throw new ArgumentNullException(nameof(orderBy)); // start with base query, and apply the supplied IQuery - if (query == null) query = UnitOfWork.SqlContext.Query(); + if (query == null) query = AmbientScope.SqlContext.Query(); var sql = new SqlTranslator(GetBaseQuery(QueryType.Many), query).Translate(); // sort and filter - sql = PrepareSqlForPagedResults(sql, filterSql, orderBy, orderDirection, orderBySystemField); + sql = PrepareSqlForPage(sql, filterSql, orderBy, orderDirection, orderBySystemField); // get a page of DTOs and the total count var pagedResult = Database.Page(pageIndex + 1, pageSize, sql); @@ -539,49 +540,49 @@ namespace Umbraco.Core.Persistence.Repositories.Implement #region UnitOfWork Events - public class UnitOfWorkEntityEventArgs : EventArgs + public class ScopedEntityEventArgs : EventArgs { - public UnitOfWorkEntityEventArgs(IScopeUnitOfWork unitOfWork, TEntity entity) + public ScopedEntityEventArgs(IScope scope, TEntity entity) { - UnitOfWork = unitOfWork; + Scope = scope; Entity = entity; } - public IScopeUnitOfWork UnitOfWork { get; } + public IScope Scope { get; } public TEntity Entity { get; } } - public class UnitOfWorkVersionEventArgs : EventArgs + public class ScopedVersionEventArgs : EventArgs { - public UnitOfWorkVersionEventArgs(IScopeUnitOfWork unitOfWork, int entityId, int versionId) + public ScopedVersionEventArgs(IScope scope, int entityId, int versionId) { - UnitOfWork = unitOfWork; + Scope = scope; EntityId = entityId; VersionId = versionId; } - public IScopeUnitOfWork UnitOfWork { get; } + public IScope Scope { get; } public int EntityId { get; } public int VersionId { get; } } - public static event TypedEventHandler UowRefreshedEntity; - public static event TypedEventHandler UowRemovingEntity; - public static event TypedEventHandler UowRemovingVersion; + public static event TypedEventHandler ScopedEntityRefresh; + public static event TypedEventHandler ScopeEntityRemove; + public static event TypedEventHandler ScopeVersionRemove; - protected void OnUowRefreshedEntity(UnitOfWorkEntityEventArgs args) + protected void OnUowRefreshedEntity(ScopedEntityEventArgs args) { - UowRefreshedEntity.RaiseEvent(args, This); + ScopedEntityRefresh.RaiseEvent(args, This); } - protected void OnUowRemovingEntity(UnitOfWorkEntityEventArgs args) + protected void OnUowRemovingEntity(ScopedEntityEventArgs args) { - UowRemovingEntity.RaiseEvent(args, This); + ScopeEntityRemove.RaiseEvent(args, This); } - protected void OnUowRemovingVersion(UnitOfWorkVersionEventArgs args) + protected void OnUowRemovingVersion(ScopedVersionEventArgs args) { - UowRemovingVersion.RaiseEvent(args, This); + ScopeVersionRemove.RaiseEvent(args, This); } #endregion diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/ContentTypeRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/ContentTypeRepository.cs index 6926085a5a..d1866d3fd2 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/ContentTypeRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/ContentTypeRepository.cs @@ -10,6 +10,7 @@ using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence.Querying; using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Core.Persistence.UnitOfWork; +using Umbraco.Core.Scoping; namespace Umbraco.Core.Persistence.Repositories.Implement { @@ -19,10 +20,9 @@ namespace Umbraco.Core.Persistence.Repositories.Implement internal class ContentTypeRepository : ContentTypeRepositoryBase, IContentTypeRepository { private readonly ITemplateRepository _templateRepository; - private IRepositoryCachePolicy _cachePolicy; - public ContentTypeRepository(IScopeUnitOfWork work, CacheHelper cache, ILogger logger, ITemplateRepository templateRepository) - : base(work, cache, logger) + public ContentTypeRepository(ScopeProvider scopeProvider, CacheHelper cache, ILogger logger, ITemplateRepository templateRepository) + : base(scopeProvider, cache, logger) { _templateRepository = templateRepository; } diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/ContentTypeRepositoryBase.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/ContentTypeRepositoryBase.cs index 2f82952f2a..6f7f585be9 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/ContentTypeRepositoryBase.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/ContentTypeRepositoryBase.cs @@ -16,6 +16,7 @@ using Umbraco.Core.Persistence.Factories; using Umbraco.Core.Persistence.Querying; using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Core.Persistence.UnitOfWork; +using Umbraco.Core.Scoping; using Umbraco.Core.Services; namespace Umbraco.Core.Persistence.Repositories.Implement @@ -28,8 +29,8 @@ namespace Umbraco.Core.Persistence.Repositories.Implement internal abstract class ContentTypeRepositoryBase : NPocoRepositoryBase, IReadRepository where TEntity : class, IContentTypeComposition { - protected ContentTypeRepositoryBase(IScopeUnitOfWork work, CacheHelper cache, ILogger logger) - : base(work, cache, logger) + protected ContentTypeRepositoryBase(ScopeProvider scopeProvider, CacheHelper cache, ILogger logger) + : base(scopeProvider, cache, logger) { } protected abstract bool IsPublishing { get; } diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/DataTypeContainerRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/DataTypeContainerRepository.cs index 78e5f27d8a..83fd58f3c2 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/DataTypeContainerRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/DataTypeContainerRepository.cs @@ -1,13 +1,13 @@ using Umbraco.Core.Cache; using Umbraco.Core.Logging; -using Umbraco.Core.Persistence.UnitOfWork; +using Umbraco.Core.Scoping; namespace Umbraco.Core.Persistence.Repositories.Implement { class DataTypeContainerRepository : EntityContainerRepository, IDataTypeContainerRepository { - public DataTypeContainerRepository(IScopeUnitOfWork uow, CacheHelper cache, ILogger logger) - : base(uow, cache, logger, Constants.ObjectTypes.DataTypeContainer) + public DataTypeContainerRepository(ScopeProvider scopeProvider, CacheHelper cache, ILogger logger) + : base(scopeProvider, cache, logger, Constants.ObjectTypes.DataTypeContainer) { } } } diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/DataTypeDefinitionRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/DataTypeDefinitionRepository.cs index b2f6454119..ac30a60f9a 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/DataTypeDefinitionRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/DataTypeDefinitionRepository.cs @@ -14,6 +14,7 @@ using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence.Factories; using Umbraco.Core.Persistence.Querying; using Umbraco.Core.Persistence.UnitOfWork; +using Umbraco.Core.Scoping; using Umbraco.Core.Services; namespace Umbraco.Core.Persistence.Repositories.Implement @@ -26,11 +27,11 @@ namespace Umbraco.Core.Persistence.Repositories.Implement private readonly IContentTypeRepository _contentTypeRepository; private readonly DataTypePreValueRepository _preValRepository; - public DataTypeDefinitionRepository(IScopeUnitOfWork work, CacheHelper cache, ILogger logger, IContentTypeRepository contentTypeRepository) - : base(work, cache, logger) + public DataTypeDefinitionRepository(ScopeProvider scopeProvider, CacheHelper cache, ILogger logger, IContentTypeRepository contentTypeRepository) + : base(scopeProvider, cache, logger) { _contentTypeRepository = contentTypeRepository; - _preValRepository = new DataTypePreValueRepository(work, CacheHelper.NoCache, logger); + _preValRepository = new DataTypePreValueRepository(scopeProvider, CacheHelper.NoCache, logger); } #region Overrides of RepositoryBase @@ -478,8 +479,8 @@ AND umbracoNode.id <> @id", /// private class DataTypePreValueRepository : NPocoRepositoryBase { - public DataTypePreValueRepository(IScopeUnitOfWork work, CacheHelper cache, ILogger logger) - : base(work, cache, logger) + public DataTypePreValueRepository(ScopeProvider scopeProvider, CacheHelper cache, ILogger logger) + : base(scopeProvider, cache, logger) { } #region Not implemented (don't need to for the purposes of this repo) diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/DictionaryRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/DictionaryRepository.cs index b8a1f30350..abfb1d2686 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/DictionaryRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/DictionaryRepository.cs @@ -10,6 +10,7 @@ using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence.Factories; using Umbraco.Core.Persistence.Querying; using Umbraco.Core.Persistence.UnitOfWork; +using Umbraco.Core.Scoping; namespace Umbraco.Core.Persistence.Repositories.Implement { @@ -18,8 +19,8 @@ namespace Umbraco.Core.Persistence.Repositories.Implement /// internal class DictionaryRepository : NPocoRepositoryBase, IDictionaryRepository { - public DictionaryRepository(IScopeUnitOfWork work, CacheHelper cache, ILogger logger) - : base(work, cache, logger) + public DictionaryRepository(ScopeProvider scopeProvider, CacheHelper cache, ILogger logger) + : base(scopeProvider, cache, logger) { } protected override IRepositoryCachePolicy CreateCachePolicy(IRuntimeCacheProvider runtimeCache) @@ -230,13 +231,13 @@ namespace Umbraco.Core.Persistence.Repositories.Implement public IDictionaryItem Get(Guid uniqueId) { - var uniqueIdRepo = new DictionaryByUniqueIdRepository(this, UnitOfWork, GlobalCache, Logger); + var uniqueIdRepo = new DictionaryByUniqueIdRepository(this, ScopeProvider, GlobalCache, Logger); return uniqueIdRepo.Get(uniqueId); } public IDictionaryItem Get(string key) { - var keyRepo = new DictionaryByKeyRepository(this, UnitOfWork, GlobalCache, Logger); + var keyRepo = new DictionaryByKeyRepository(this, ScopeProvider, GlobalCache, Logger); return keyRepo.Get(key); } @@ -294,11 +295,10 @@ namespace Umbraco.Core.Persistence.Repositories.Implement private class DictionaryByUniqueIdRepository : SimpleGetRepository { - private IRepositoryCachePolicy _cachePolicy; private readonly DictionaryRepository _dictionaryRepository; - public DictionaryByUniqueIdRepository(DictionaryRepository dictionaryRepository, IScopeUnitOfWork work, CacheHelper cache, ILogger logger) - : base(work, cache, logger) + public DictionaryByUniqueIdRepository(DictionaryRepository dictionaryRepository, ScopeProvider scopeProvider, CacheHelper cache, ILogger logger) + : base(scopeProvider, cache, logger) { _dictionaryRepository = dictionaryRepository; } @@ -348,11 +348,10 @@ namespace Umbraco.Core.Persistence.Repositories.Implement private class DictionaryByKeyRepository : SimpleGetRepository { - private IRepositoryCachePolicy _cachePolicy; private readonly DictionaryRepository _dictionaryRepository; - public DictionaryByKeyRepository(DictionaryRepository dictionaryRepository, IScopeUnitOfWork work, CacheHelper cache, ILogger logger) - : base(work, cache, logger) + public DictionaryByKeyRepository(DictionaryRepository dictionaryRepository, ScopeProvider scopeProvider, CacheHelper cache, ILogger logger) + : base(scopeProvider, cache, logger) { _dictionaryRepository = dictionaryRepository; } diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentBlueprintRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentBlueprintRepository.cs index 98de1179e4..0e2020babb 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentBlueprintRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentBlueprintRepository.cs @@ -3,6 +3,7 @@ using Umbraco.Core.Cache; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Logging; using Umbraco.Core.Persistence.UnitOfWork; +using Umbraco.Core.Scoping; namespace Umbraco.Core.Persistence.Repositories.Implement { @@ -17,8 +18,8 @@ namespace Umbraco.Core.Persistence.Repositories.Implement /// internal class DocumentBlueprintRepository : DocumentRepository, IDocumentBlueprintRepository { - public DocumentBlueprintRepository(IScopeUnitOfWork work, CacheHelper cacheHelper, ILogger logger, IContentTypeRepository contentTypeRepository, ITemplateRepository templateRepository, ITagRepository tagRepository, IContentSection settings) - : base(work, cacheHelper, logger, contentTypeRepository, templateRepository, tagRepository, settings) + public DocumentBlueprintRepository(ScopeProvider scopeProvider, CacheHelper cacheHelper, ILogger logger, IContentTypeRepository contentTypeRepository, ITemplateRepository templateRepository, ITagRepository tagRepository, IContentSection settings) + : base(scopeProvider, cacheHelper, logger, contentTypeRepository, templateRepository, tagRepository, settings) { EnsureUniqueNaming = false; // duplicates are allowed } diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentRepository.cs index 9e4796a049..1dd8653cda 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentRepository.cs @@ -14,6 +14,7 @@ using Umbraco.Core.Persistence.Factories; using Umbraco.Core.Persistence.Querying; using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Core.Persistence.UnitOfWork; +using Umbraco.Core.Scoping; namespace Umbraco.Core.Persistence.Repositories.Implement { @@ -22,6 +23,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement /// internal class DocumentRepository : ContentRepositoryBase, IDocumentRepository { + private readonly ScopeProvider _scopeProvider; private readonly IContentTypeRepository _contentTypeRepository; private readonly ITemplateRepository _templateRepository; private readonly ITagRepository _tagRepository; @@ -29,14 +31,14 @@ namespace Umbraco.Core.Persistence.Repositories.Implement private PermissionRepository _permissionRepository; private readonly ContentByGuidReadRepository _contentByGuidReadRepository; - public DocumentRepository(IScopeUnitOfWork work, CacheHelper cacheHelper, ILogger logger, IContentTypeRepository contentTypeRepository, ITemplateRepository templateRepository, ITagRepository tagRepository, IContentSection settings) - : base(work, cacheHelper, logger) + public DocumentRepository(ScopeProvider scopeProvider, CacheHelper cacheHelper, ILogger logger, IContentTypeRepository contentTypeRepository, ITemplateRepository templateRepository, ITagRepository tagRepository, IContentSection settings) + : base(scopeProvider, cacheHelper, logger) { _contentTypeRepository = contentTypeRepository ?? throw new ArgumentNullException(nameof(contentTypeRepository)); _templateRepository = templateRepository ?? throw new ArgumentNullException(nameof(templateRepository)); _tagRepository = tagRepository ?? throw new ArgumentNullException(nameof(tagRepository)); _cacheHelper = cacheHelper; - _contentByGuidReadRepository = new ContentByGuidReadRepository(this, work, cacheHelper, logger); + _contentByGuidReadRepository = new ContentByGuidReadRepository(this, scopeProvider, cacheHelper, logger); EnsureUniqueNaming = settings.EnsureUniqueNaming; } @@ -46,7 +48,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement // note: is ok to 'new' the repo here as it's a sub-repo really private PermissionRepository PermissionRepository => _permissionRepository - ?? (_permissionRepository = new PermissionRepository(UnitOfWork, _cacheHelper, Logger)); + ?? (_permissionRepository = new PermissionRepository(_scopeProvider, _cacheHelper, Logger)); #region Repository Base @@ -213,7 +215,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement protected override void PerformDeleteVersion(int id, int versionId) { // raise event first else potential FK issues - OnUowRemovingVersion(new UnitOfWorkVersionEventArgs(UnitOfWork, id, versionId)); + OnUowRemovingVersion(new ScopedVersionEventArgs(AmbientScope, id, versionId)); // fixme - syntax + ... Database.Delete("WHERE versionId = @versionId", new { versionId }); @@ -325,7 +327,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement Database.Insert(dto); // trigger here, before we reset Published etc - OnUowRefreshedEntity(new UnitOfWorkEntityEventArgs(UnitOfWork, entity)); + OnUowRefreshedEntity(new ScopedEntityEventArgs(AmbientScope, entity)); // flip the entity's published property // this also flips its published state @@ -467,7 +469,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement UpdateEntityTags(entity, _tagRepository); // trigger here, before we reset Published etc - OnUowRefreshedEntity(new UnitOfWorkEntityEventArgs(UnitOfWork, entity)); + OnUowRefreshedEntity(new ScopedEntityEventArgs(AmbientScope, entity)); // flip the entity's published property // this also flips its published state @@ -506,7 +508,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement protected override void PersistDeletedItem(IContent entity) { // raise event first else potential FK issues - OnUowRemovingEntity(new UnitOfWorkEntityEventArgs(UnitOfWork, entity)); + OnUowRemovingEntity(new ScopedEntityEventArgs(AmbientScope, entity)); //We need to clear out all access rules but we need to do this in a manual way since // nothing in that table is joined to a content id @@ -603,7 +605,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement filterSql.Append($"AND ({filterClause.Item1})", filterClause.Item2); } - return GetPagedResultsByQuery(query, pageIndex, pageSize, out totalRecords, + return GetPage(query, pageIndex, pageSize, out totalRecords, x => MapDtosToContent(x), orderBy, orderDirection, orderBySystemField, filterSql); @@ -662,8 +664,8 @@ namespace Umbraco.Core.Persistence.Repositories.Implement { private readonly DocumentRepository _outerRepo; - public ContentByGuidReadRepository(DocumentRepository outerRepo, IScopeUnitOfWork work, CacheHelper cache, ILogger logger) - : base(work, cache, logger) + public ContentByGuidReadRepository(DocumentRepository outerRepo, ScopeProvider scopeProvider, CacheHelper cache, ILogger logger) + : base(scopeProvider, cache, logger) { _outerRepo = outerRepo; } diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentTypeContainerRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentTypeContainerRepository.cs index 13003d2377..83c606aaf1 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentTypeContainerRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentTypeContainerRepository.cs @@ -1,13 +1,13 @@ using Umbraco.Core.Cache; using Umbraco.Core.Logging; -using Umbraco.Core.Persistence.UnitOfWork; +using Umbraco.Core.Scoping; namespace Umbraco.Core.Persistence.Repositories.Implement { class DocumentTypeContainerRepository : EntityContainerRepository, IDocumentTypeContainerRepository { - public DocumentTypeContainerRepository(IScopeUnitOfWork uow, CacheHelper cache, ILogger logger) - : base(uow, cache, logger, Constants.ObjectTypes.DocumentTypeContainer) + public DocumentTypeContainerRepository(ScopeProvider scopeProvider, CacheHelper cache, ILogger logger) + : base(scopeProvider, cache, logger, Constants.ObjectTypes.DocumentTypeContainer) { } } } diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/DomainRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/DomainRepository.cs index f3af65d469..7c490e6d03 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/DomainRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/DomainRepository.cs @@ -8,7 +8,7 @@ using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence.Querying; -using Umbraco.Core.Persistence.UnitOfWork; +using Umbraco.Core.Scoping; namespace Umbraco.Core.Persistence.Repositories.Implement { @@ -16,10 +16,8 @@ namespace Umbraco.Core.Persistence.Repositories.Implement internal class DomainRepository : NPocoRepositoryBase, IDomainRepository { - private IRepositoryCachePolicy _cachePolicy; - - public DomainRepository(IScopeUnitOfWork work, CacheHelper cache, ILogger logger) - : base(work, cache, logger) + public DomainRepository(ScopeProvider scopeProvider, CacheHelper cache, ILogger logger) + : base(scopeProvider, cache, logger) { } protected override IRepositoryCachePolicy CreateCachePolicy(IRuntimeCacheProvider runtimeCache) diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/EntityContainerRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/EntityContainerRepository.cs index 4ff4ff24e0..b627857b8a 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/EntityContainerRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/EntityContainerRepository.cs @@ -9,6 +9,7 @@ using Umbraco.Core.Models; using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence.Querying; using Umbraco.Core.Persistence.UnitOfWork; +using Umbraco.Core.Scoping; namespace Umbraco.Core.Persistence.Repositories.Implement { @@ -19,8 +20,8 @@ namespace Umbraco.Core.Persistence.Repositories.Implement { private readonly Guid _containerObjectType; - public EntityContainerRepository(IScopeUnitOfWork work, CacheHelper cache, ILogger logger, Guid containerObjectType) - : base(work, cache, logger) + public EntityContainerRepository(ScopeProvider scopeProvider, CacheHelper cache, ILogger logger, Guid containerObjectType) + : base(scopeProvider, cache, logger) { var allowedContainers = new[] { Constants.ObjectTypes.DocumentTypeContainer, Constants.ObjectTypes.MediaTypeContainer, Constants.ObjectTypes.DataTypeContainer }; _containerObjectType = containerObjectType; diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/ExternalLoginRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/ExternalLoginRepository.cs index c3208c8a62..8fc2ad2fc5 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/ExternalLoginRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/ExternalLoginRepository.cs @@ -11,15 +11,15 @@ using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence.Factories; using Umbraco.Core.Persistence.Querying; using Umbraco.Core.Persistence.UnitOfWork; +using Umbraco.Core.Scoping; namespace Umbraco.Core.Persistence.Repositories.Implement { internal class ExternalLoginRepository : NPocoRepositoryBase, IExternalLoginRepository { - public ExternalLoginRepository(IScopeUnitOfWork work, CacheHelper cache, ILogger logger) - : base(work, cache, logger) - { - } + public ExternalLoginRepository(ScopeProvider scopeProvider, CacheHelper cache, ILogger logger) + : base(scopeProvider, cache, logger) + { } public void DeleteUserLogins(int memberId) { diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/LanguageRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/LanguageRepository.cs index b10335628e..9af4cb1de5 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/LanguageRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/LanguageRepository.cs @@ -10,6 +10,7 @@ using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence.Factories; using Umbraco.Core.Persistence.Querying; using Umbraco.Core.Persistence.UnitOfWork; +using Umbraco.Core.Scoping; namespace Umbraco.Core.Persistence.Repositories.Implement { @@ -18,10 +19,8 @@ namespace Umbraco.Core.Persistence.Repositories.Implement /// internal class LanguageRepository : NPocoRepositoryBase, ILanguageRepository { - private IRepositoryCachePolicy _cachePolicy; - - public LanguageRepository(IScopeUnitOfWork work, CacheHelper cache, ILogger logger) - : base(work, cache, logger) + public LanguageRepository(ScopeProvider scopeProvider, CacheHelper cache, ILogger logger) + : base(scopeProvider, cache, logger) { } protected override IRepositoryCachePolicy CreateCachePolicy(IRuntimeCacheProvider runtimeCache) diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/MacroRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/MacroRepository.cs index f7eb961305..44d15947b4 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/MacroRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/MacroRepository.cs @@ -9,14 +9,14 @@ using Umbraco.Core.Models.EntityBase; using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence.Factories; using Umbraco.Core.Persistence.Querying; -using Umbraco.Core.Persistence.UnitOfWork; +using Umbraco.Core.Scoping; namespace Umbraco.Core.Persistence.Repositories.Implement { internal class MacroRepository : NPocoRepositoryBase, IMacroRepository { - public MacroRepository(IScopeUnitOfWork work, CacheHelper cache, ILogger logger) - : base(work, cache, logger) + public MacroRepository(ScopeProvider scopeProvider, CacheHelper cache, ILogger logger) + : base(scopeProvider, cache, logger) { } protected override IMacro PerformGet(int id) diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/MediaRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/MediaRepository.cs index a508297aaf..fe2a4e80e3 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/MediaRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/MediaRepository.cs @@ -13,6 +13,7 @@ using Umbraco.Core.Persistence.DatabaseModelDefinitions; using Umbraco.Core.Persistence.Factories; using Umbraco.Core.Persistence.Querying; using Umbraco.Core.Persistence.UnitOfWork; +using Umbraco.Core.Scoping; namespace Umbraco.Core.Persistence.Repositories.Implement { @@ -25,12 +26,12 @@ namespace Umbraco.Core.Persistence.Repositories.Implement private readonly ITagRepository _tagRepository; private readonly MediaByGuidReadRepository _mediaByGuidReadRepository; - public MediaRepository(IScopeUnitOfWork work, CacheHelper cache, ILogger logger, IMediaTypeRepository mediaTypeRepository, ITagRepository tagRepository, IContentSection contentSection) - : base(work, cache, logger) + public MediaRepository(ScopeProvider scopeProvider, CacheHelper cache, ILogger logger, IMediaTypeRepository mediaTypeRepository, ITagRepository tagRepository, IContentSection contentSection) + : base(scopeProvider, cache, logger) { _mediaTypeRepository = mediaTypeRepository ?? throw new ArgumentNullException(nameof(mediaTypeRepository)); _tagRepository = tagRepository ?? throw new ArgumentNullException(nameof(tagRepository)); - _mediaByGuidReadRepository = new MediaByGuidReadRepository(this, work, cache, logger); + _mediaByGuidReadRepository = new MediaByGuidReadRepository(this, scopeProvider, cache, logger); EnsureUniqueNaming = contentSection.EnsureUniqueNaming; } @@ -216,7 +217,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement protected override void PerformDeleteVersion(int id, int versionId) { // raise event first else potential FK issues - OnUowRemovingVersion(new UnitOfWorkVersionEventArgs(UnitOfWork, id, versionId)); + OnUowRemovingVersion(new ScopedVersionEventArgs(AmbientScope, id, versionId)); Database.Delete("WHERE versionId = @versionId", new { versionId }); Database.Delete("WHERE versionId = @versionId", new { versionId }); @@ -300,7 +301,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement // set tags UpdateEntityTags(entity, _tagRepository); - OnUowRefreshedEntity(new UnitOfWorkEntityEventArgs(UnitOfWork, entity)); + OnUowRefreshedEntity(new ScopedEntityEventArgs(AmbientScope, entity)); entity.ResetDirtyProperties(); } @@ -354,7 +355,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement UpdateEntityTags(entity, _tagRepository); - OnUowRefreshedEntity(new UnitOfWorkEntityEventArgs(UnitOfWork, entity)); + OnUowRefreshedEntity(new ScopedEntityEventArgs(AmbientScope, entity)); entity.ResetDirtyProperties(); } @@ -362,7 +363,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement protected override void PersistDeletedItem(IMedia entity) { // raise event first else potential FK issues - OnUowRemovingEntity(new UnitOfWorkEntityEventArgs(UnitOfWork, entity)); + OnUowRemovingEntity(new ScopedEntityEventArgs(AmbientScope, entity)); base.PersistDeletedItem(entity); } @@ -402,8 +403,8 @@ namespace Umbraco.Core.Persistence.Repositories.Implement { private readonly MediaRepository _outerRepo; - public MediaByGuidReadRepository(MediaRepository outerRepo, IScopeUnitOfWork work, CacheHelper cache, ILogger logger) - : base(work, cache, logger) + public MediaByGuidReadRepository(MediaRepository outerRepo, ScopeProvider scopeProvider, CacheHelper cache, ILogger logger) + : base(scopeProvider, cache, logger) { _outerRepo = outerRepo; } @@ -482,7 +483,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement filterSql = filterSql.Append($"AND ({clause.Item1})", clause.Item2); } - return GetPagedResultsByQuery(query, pageIndex, pageSize, out totalRecords, + return GetPage(query, pageIndex, pageSize, out totalRecords, x => MapDtosToContent(x), orderBy, orderDirection, orderBySystemField, filterSql); } diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/MediaTypeContainerRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/MediaTypeContainerRepository.cs index be371a60f5..ddb189b1d5 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/MediaTypeContainerRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/MediaTypeContainerRepository.cs @@ -1,13 +1,13 @@ using Umbraco.Core.Cache; using Umbraco.Core.Logging; -using Umbraco.Core.Persistence.UnitOfWork; +using Umbraco.Core.Scoping; namespace Umbraco.Core.Persistence.Repositories.Implement { class MediaTypeContainerRepository : EntityContainerRepository, IMediaTypeContainerRepository { - public MediaTypeContainerRepository(IScopeUnitOfWork uow, CacheHelper cache, ILogger logger) - : base(uow, cache, logger, Constants.ObjectTypes.MediaTypeContainer) + public MediaTypeContainerRepository(ScopeProvider scopeProvider, CacheHelper cache, ILogger logger) + : base(scopeProvider, cache, logger, Constants.ObjectTypes.MediaTypeContainer) { } } } diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/MediaTypeRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/MediaTypeRepository.cs index d162b8a353..a9c810b414 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/MediaTypeRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/MediaTypeRepository.cs @@ -8,6 +8,7 @@ using Umbraco.Core.Models; using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence.Querying; using Umbraco.Core.Persistence.UnitOfWork; +using Umbraco.Core.Scoping; namespace Umbraco.Core.Persistence.Repositories.Implement { @@ -16,10 +17,8 @@ namespace Umbraco.Core.Persistence.Repositories.Implement /// internal class MediaTypeRepository : ContentTypeRepositoryBase, IMediaTypeRepository { - private IRepositoryCachePolicy _cachePolicy; - - public MediaTypeRepository(IScopeUnitOfWork work, CacheHelper cache, ILogger logger) - : base(work, cache, logger) + public MediaTypeRepository(ScopeProvider scopeProvider, CacheHelper cache, ILogger logger) + : base(scopeProvider, cache, logger) { } protected override bool IsPublishing => MediaType.IsPublishingConst; diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/MemberGroupRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/MemberGroupRepository.cs index a35a157782..28c88d0352 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/MemberGroupRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/MemberGroupRepository.cs @@ -9,14 +9,14 @@ using Umbraco.Core.Models; using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence.Factories; using Umbraco.Core.Persistence.Querying; -using Umbraco.Core.Persistence.UnitOfWork; +using Umbraco.Core.Scoping; namespace Umbraco.Core.Persistence.Repositories.Implement { internal class MemberGroupRepository : NPocoRepositoryBase, IMemberGroupRepository { - public MemberGroupRepository(IScopeUnitOfWork work, CacheHelper cache, ILogger logger) - : base(work, cache, logger) + public MemberGroupRepository(ScopeProvider scopeProvider, CacheHelper cache, ILogger logger) + : base(scopeProvider, cache, logger) { } private readonly MemberGroupFactory _modelFactory = new MemberGroupFactory(); @@ -145,10 +145,10 @@ namespace Umbraco.Core.Persistence.Repositories.Implement }; PersistNewItem(grp); - if (UnitOfWork.Events.DispatchCancelable(SavingMemberGroup, this, new SaveEventArgs(grp))) + if (AmbientScope.Events.DispatchCancelable(SavingMemberGroup, this, new SaveEventArgs(grp))) return null; - UnitOfWork.Events.Dispatch(SavedMemberGroup, this, new SaveEventArgs(grp)); + AmbientScope.Events.Dispatch(SavedMemberGroup, this, new SaveEventArgs(grp)); return grp; } @@ -239,13 +239,13 @@ namespace Umbraco.Core.Persistence.Repositories.Implement var missingRoles = roleNames.Except(existingRoles); var missingGroups = missingRoles.Select(x => new MemberGroup {Name = x}).ToArray(); - if (UnitOfWork.Events.DispatchCancelable(SavingMemberGroup, this, new SaveEventArgs(missingGroups))) + if (AmbientScope.Events.DispatchCancelable(SavingMemberGroup, this, new SaveEventArgs(missingGroups))) return; foreach (var m in missingGroups) PersistNewItem(m); - UnitOfWork.Events.Dispatch(SavedMemberGroup, this, new SaveEventArgs(missingGroups)); + AmbientScope.Events.Dispatch(SavedMemberGroup, this, new SaveEventArgs(missingGroups)); //now go get all the dto's for roles with these role names var rolesForNames = Database.Fetch(existingSql).ToArray(); diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/MemberRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/MemberRepository.cs index ebe09729ff..40b76d05c5 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/MemberRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/MemberRepository.cs @@ -11,6 +11,7 @@ using Umbraco.Core.Persistence.DatabaseModelDefinitions; using Umbraco.Core.Persistence.Factories; using Umbraco.Core.Persistence.Querying; using Umbraco.Core.Persistence.UnitOfWork; +using Umbraco.Core.Scoping; namespace Umbraco.Core.Persistence.Repositories.Implement { @@ -23,8 +24,8 @@ namespace Umbraco.Core.Persistence.Repositories.Implement private readonly ITagRepository _tagRepository; private readonly IMemberGroupRepository _memberGroupRepository; - public MemberRepository(IScopeUnitOfWork work, CacheHelper cache, ILogger logger, IMemberTypeRepository memberTypeRepository, IMemberGroupRepository memberGroupRepository, ITagRepository tagRepository) - : base(work, cache, logger) + public MemberRepository(ScopeProvider scopeProvider, CacheHelper cache, ILogger logger, IMemberTypeRepository memberTypeRepository, IMemberGroupRepository memberGroupRepository, ITagRepository tagRepository) + : base(scopeProvider, cache, logger) { _memberTypeRepository = memberTypeRepository ?? throw new ArgumentNullException(nameof(memberTypeRepository)); _tagRepository = tagRepository ?? throw new ArgumentNullException(nameof(tagRepository)); @@ -217,7 +218,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement protected override void PerformDeleteVersion(int id, int versionId) { // raise event first else potential FK issues - OnUowRemovingVersion(new UnitOfWorkVersionEventArgs(UnitOfWork, id, versionId)); + OnUowRemovingVersion(new ScopedVersionEventArgs(AmbientScope, id, versionId)); Database.Delete("WHERE versionId = @VersionId", new { versionId }); Database.Delete("WHERE versionId = @VersionId", new { versionId }); @@ -312,7 +313,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement UpdateEntityTags(entity, _tagRepository); - OnUowRefreshedEntity(new UnitOfWorkEntityEventArgs(UnitOfWork, entity)); + OnUowRefreshedEntity(new ScopedEntityEventArgs(AmbientScope, entity)); entity.ResetDirtyProperties(); } @@ -377,7 +378,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement UpdateEntityTags(entity, _tagRepository); - OnUowRefreshedEntity(new UnitOfWorkEntityEventArgs(UnitOfWork, entity)); + OnUowRefreshedEntity(new ScopedEntityEventArgs(AmbientScope, entity)); entity.ResetDirtyProperties(); } @@ -385,7 +386,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement protected override void PersistDeletedItem(IMember entity) { // raise event first else potential FK issues - OnUowRemovingEntity(new UnitOfWorkEntityEventArgs(UnitOfWork, entity)); + OnUowRemovingEntity(new ScopedEntityEventArgs(AmbientScope, entity)); base.PersistDeletedItem(entity); } @@ -504,7 +505,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement filterSql = filterSql.Append($"AND ({clause.Item1})", clause.Item2); } - return GetPagedResultsByQuery(query, pageIndex, pageSize, out totalRecords, + return GetPage(query, pageIndex, pageSize, out totalRecords, x => MapDtosToContent(x), orderBy, orderDirection, orderBySystemField, filterSql); } diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/MemberTypeRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/MemberTypeRepository.cs index 6e753c8e69..5b3c047396 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/MemberTypeRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/MemberTypeRepository.cs @@ -8,7 +8,7 @@ using Umbraco.Core.Models; using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence.Factories; using Umbraco.Core.Persistence.Querying; -using Umbraco.Core.Persistence.UnitOfWork; +using Umbraco.Core.Scoping; namespace Umbraco.Core.Persistence.Repositories.Implement { @@ -17,10 +17,8 @@ namespace Umbraco.Core.Persistence.Repositories.Implement /// internal class MemberTypeRepository : ContentTypeRepositoryBase, IMemberTypeRepository { - private IRepositoryCachePolicy _cachePolicy; - - public MemberTypeRepository(IScopeUnitOfWork work, CacheHelper cache, ILogger logger) - : base(work, cache, logger) + public MemberTypeRepository(ScopeProvider scopeProvider, CacheHelper cache, ILogger logger) + : base(scopeProvider, cache, logger) { } protected override bool IsPublishing => MemberType.IsPublishingConst; diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/MigrationEntryRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/MigrationEntryRepository.cs index 178eb24089..0eb693c962 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/MigrationEntryRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/MigrationEntryRepository.cs @@ -11,16 +11,15 @@ using Umbraco.Core.Models; using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence.Factories; using Umbraco.Core.Persistence.Querying; -using Umbraco.Core.Persistence.UnitOfWork; +using Umbraco.Core.Scoping; namespace Umbraco.Core.Persistence.Repositories.Implement { internal class MigrationEntryRepository : NPocoRepositoryBase, IMigrationEntryRepository { - public MigrationEntryRepository(IScopeUnitOfWork work, [Inject(RepositoryCompositionRoot.DisabledCache)] CacheHelper cache, ILogger logger) - : base(work, cache, logger) - { - } + public MigrationEntryRepository(ScopeProvider scopeProvider, [Inject(RepositoryCompositionRoot.DisabledCache)] CacheHelper cache, ILogger logger) + : base(scopeProvider, cache, logger) + { } protected override IMigrationEntry PerformGet(int id) { diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/NPocoRepositoryBase.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/NPocoRepositoryBase.cs index 75b27d093a..207f3de0f4 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/NPocoRepositoryBase.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/NPocoRepositoryBase.cs @@ -7,6 +7,7 @@ using Umbraco.Core.Models.EntityBase; using Umbraco.Core.Persistence.Querying; using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Core.Persistence.UnitOfWork; +using Umbraco.Core.Scoping; namespace Umbraco.Core.Persistence.Repositories.Implement { @@ -19,29 +20,21 @@ namespace Umbraco.Core.Persistence.Repositories.Implement where TEntity : class, IAggregateRoot { /// - /// Initializes a new instance of the . + /// Initializes a new instance of the class. /// - /// A database unit of work. - /// A cache helper. - /// A logger. - protected NPocoRepositoryBase(IScopeUnitOfWork work, CacheHelper cache, ILogger logger) - : base(work, cache, logger) + protected NPocoRepositoryBase(ScopeProvider scopeProvider, CacheHelper cache, ILogger logger) + : base(scopeProvider, cache, logger) { } - /// - /// Gets the repository's unit of work. - /// - protected internal new IScopeUnitOfWork UnitOfWork => base.UnitOfWork; - /// /// Gets the repository's database. /// - protected IUmbracoDatabase Database => UnitOfWork.Database; + protected IUmbracoDatabase Database => AmbientScope.Database; /// /// Gets the Sql context. /// - protected ISqlContext SqlContext=> UnitOfWork.SqlContext; + protected ISqlContext SqlContext=> AmbientScope.SqlContext; protected Sql Sql() => SqlContext.Sql(); protected Sql Sql(string sql, params object[] args) => SqlContext.Sql(sql, args); diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/PermissionRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/PermissionRepository.cs index e6b4469ec4..d23255f956 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/PermissionRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/PermissionRepository.cs @@ -11,6 +11,7 @@ using Umbraco.Core.Models.Membership; using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence.Querying; using Umbraco.Core.Persistence.UnitOfWork; +using Umbraco.Core.Scoping; namespace Umbraco.Core.Persistence.Repositories.Implement { @@ -25,8 +26,8 @@ namespace Umbraco.Core.Persistence.Repositories.Implement internal class PermissionRepository : NPocoRepositoryBase where TEntity : class, IAggregateRoot { - public PermissionRepository(IScopeUnitOfWork work, CacheHelper cache, ILogger logger) - : base(work, cache, logger) + public PermissionRepository(ScopeProvider scopeProvider, CacheHelper cache, ILogger logger) + : base(scopeProvider, cache, logger) { } /// @@ -55,7 +56,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement .SelectAll() .From() .Where(dto => localIds.Contains(dto.UserGroupId)); - var permissions = UnitOfWork.Database.Fetch(sql); + var permissions = AmbientScope.Database.Fetch(sql); foreach (var permission in ConvertToPermissionList(permissions)) { result.Add(permission); @@ -71,7 +72,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement .SelectAll() .From() .Where(dto => localIds.Contains(dto.UserGroupId) && ids.Contains(dto.NodeId)); - var permissions = UnitOfWork.Database.Fetch(sql); + var permissions = AmbientScope.Database.Fetch(sql); foreach (var permission in ConvertToPermissionList(permissions)) { result.Add(permission); @@ -96,7 +97,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement .Where(dto => entityIds.Contains(dto.NodeId)) .OrderBy(dto => dto.NodeId); - var result = UnitOfWork.Database.Fetch(sql); + var result = AmbientScope.Database.Fetch(sql); return ConvertToPermissionList(result); } @@ -113,7 +114,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement .Where(dto => dto.NodeId == entityId) .OrderBy(dto => dto.NodeId); - var result = UnitOfWork.Database.Fetch(sql); + var result = AmbientScope.Database.Fetch(sql); return ConvertToPermissionList(result); } @@ -131,7 +132,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement if (entityIds.Length == 0) return; - var db = UnitOfWork.Database; + var db = AmbientScope.Database; //we need to batch these in groups of 2000 so we don't exceed the max 2100 limit var sql = "DELETE FROM umbracoUserGroup2NodePermission WHERE userGroupId = @groupId AND nodeId in (@nodeIds)"; @@ -165,7 +166,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement /// public void AssignPermission(int groupId, char permission, params int[] entityIds) { - var db = UnitOfWork.Database; + var db = AmbientScope.Database; var sql = "DELETE FROM umbracoUserGroup2NodePermission WHERE userGroupId = @groupId AND permission=@permission AND nodeId in (@entityIds)"; db.Execute(sql, @@ -194,7 +195,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement /// public void AssignEntityPermission(TEntity entity, char permission, IEnumerable groupIds) { - var db = UnitOfWork.Database; + var db = AmbientScope.Database; var groupIdsA = groupIds.ToArray(); const string sql = "DELETE FROM umbracoUserGroup2NodePermission WHERE nodeId = @nodeId AND permission = @permission AND userGroupId in (@groupIds)"; @@ -226,7 +227,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement /// public void ReplaceEntityPermissions(EntityPermissionSet permissionSet) { - var db = UnitOfWork.Database; + var db = AmbientScope.Database; const string sql = "DELETE FROM umbracoUserGroup2NodePermission WHERE nodeId = @nodeId"; db.Execute(sql, new { nodeId = permissionSet.EntityId }); diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/PublicAccessRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/PublicAccessRepository.cs index 2883bb1dbd..7d09b2f829 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/PublicAccessRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/PublicAccessRepository.cs @@ -8,14 +8,14 @@ using Umbraco.Core.Models; using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence.Factories; using Umbraco.Core.Persistence.Querying; -using Umbraco.Core.Persistence.UnitOfWork; +using Umbraco.Core.Scoping; namespace Umbraco.Core.Persistence.Repositories.Implement { internal class PublicAccessRepository : NPocoRepositoryBase, IPublicAccessRepository { - public PublicAccessRepository(IScopeUnitOfWork work, CacheHelper cache, ILogger logger) - : base(work, cache, logger) + public PublicAccessRepository(ScopeProvider scopeProvider, CacheHelper cache, ILogger logger) + : base(scopeProvider, cache, logger) { } protected override IRepositoryCachePolicy CreateCachePolicy(IRuntimeCacheProvider runtimeCache) diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/RedirectUrlRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/RedirectUrlRepository.cs index 8d01c48750..6093085c42 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/RedirectUrlRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/RedirectUrlRepository.cs @@ -7,14 +7,14 @@ using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence.Querying; -using Umbraco.Core.Persistence.UnitOfWork; +using Umbraco.Core.Scoping; namespace Umbraco.Core.Persistence.Repositories.Implement { internal class RedirectUrlRepository : NPocoRepositoryBase, IRedirectUrlRepository { - public RedirectUrlRepository(IScopeUnitOfWork work, CacheHelper cache, ILogger logger) - : base(work, cache, logger) + public RedirectUrlRepository(ScopeProvider scopeProvider, CacheHelper cache, ILogger logger) + : base(scopeProvider, cache, logger) { } protected override int PerformCount(IQuery query) diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/RelationRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/RelationRepository.cs index 4b2583e2f0..c8a6f14b66 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/RelationRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/RelationRepository.cs @@ -12,6 +12,7 @@ using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence.Factories; using Umbraco.Core.Persistence.Querying; using Umbraco.Core.Persistence.UnitOfWork; +using Umbraco.Core.Scoping; namespace Umbraco.Core.Persistence.Repositories.Implement { @@ -22,8 +23,8 @@ namespace Umbraco.Core.Persistence.Repositories.Implement { private readonly IRelationTypeRepository _relationTypeRepository; - public RelationRepository(IScopeUnitOfWork work, [Inject(RepositoryCompositionRoot.DisabledCache)] CacheHelper cache, ILogger logger, IRelationTypeRepository relationTypeRepository) - : base(work, cache, logger) + public RelationRepository(ScopeProvider scopeProvider, [Inject(RepositoryCompositionRoot.DisabledCache)] CacheHelper cache, ILogger logger, IRelationTypeRepository relationTypeRepository) + : base(scopeProvider, cache, logger) { _relationTypeRepository = relationTypeRepository; } diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/RelationTypeRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/RelationTypeRepository.cs index 00ee49bda1..2724303f3c 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/RelationTypeRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/RelationTypeRepository.cs @@ -9,7 +9,7 @@ using Umbraco.Core.Models.EntityBase; using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence.Factories; using Umbraco.Core.Persistence.Querying; -using Umbraco.Core.Persistence.UnitOfWork; +using Umbraco.Core.Scoping; namespace Umbraco.Core.Persistence.Repositories.Implement { @@ -18,8 +18,8 @@ namespace Umbraco.Core.Persistence.Repositories.Implement /// internal class RelationTypeRepository : NPocoRepositoryBase, IRelationTypeRepository { - public RelationTypeRepository(IScopeUnitOfWork work, CacheHelper cache, ILogger logger) - : base(work, cache, logger) + public RelationTypeRepository(ScopeProvider scopeProvider, CacheHelper cache, ILogger logger) + : base(scopeProvider, cache, logger) { } protected override IRepositoryCachePolicy CreateCachePolicy(IRuntimeCacheProvider runtimeCache) diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/RepositoryBaseOfTIdTEntity.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/RepositoryBaseOfTIdTEntity.cs index b23e347e79..f2ac006f42 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/RepositoryBaseOfTIdTEntity.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/RepositoryBaseOfTIdTEntity.cs @@ -5,7 +5,6 @@ using Umbraco.Core.Cache; using Umbraco.Core.Logging; using Umbraco.Core.Models.EntityBase; using Umbraco.Core.Persistence.Querying; -using Umbraco.Core.Persistence.UnitOfWork; using Umbraco.Core.Scoping; namespace Umbraco.Core.Persistence.Repositories.Implement @@ -15,24 +14,35 @@ namespace Umbraco.Core.Persistence.Repositories.Implement /// /// The type of the entity managed by this repository. /// The type of the entity's unique identifier. - internal abstract class RepositoryBase : IReadWriteQueryRepository, IUnitOfWorkRepository + internal abstract class RepositoryBase : IReadWriteQueryRepository where TEntity : class, IAggregateRoot { private IRepositoryCachePolicy _cachePolicy; private IRuntimeCacheProvider _isolatedCache; - protected RepositoryBase(IScopeUnitOfWork work, CacheHelper cache, ILogger logger) + protected RepositoryBase(ScopeProvider scopeProvider, CacheHelper cache, ILogger logger) { + ScopeProvider = scopeProvider ?? throw new ArgumentNullException(nameof(scopeProvider)); Logger = logger ?? throw new ArgumentNullException(nameof(logger)); - UnitOfWork = work ?? throw new ArgumentNullException(nameof(work)); GlobalCache = cache ?? throw new ArgumentNullException(nameof(cache)); } - protected IScopeUnitOfWork UnitOfWork { get; } + protected ILogger Logger { get; } protected CacheHelper GlobalCache { get; } - protected ILogger Logger { get; } + protected ScopeProvider ScopeProvider { get; } + + protected IScope AmbientScope + { + get + { + var scope = ScopeProvider.AmbientScope; + if (scope == null) + throw new InvalidOperationException("Cannot run a repository without an ambient scope."); + return scope; + } + } #region Static Queries @@ -54,15 +64,14 @@ namespace Umbraco.Core.Persistence.Repositories.Implement { if (_isolatedCache != null) return _isolatedCache; - var scope = UnitOfWork.Scope; IsolatedRuntimeCache provider; - switch (scope.RepositoryCacheMode) + switch (AmbientScope.RepositoryCacheMode) { case RepositoryCacheMode.Default: provider = GlobalCache.IsolatedRuntimeCache; break; case RepositoryCacheMode.Scoped: - provider = scope.IsolatedRuntimeCache; + provider = AmbientScope.IsolatedRuntimeCache; break; case RepositoryCacheMode.None: return new NullCacheProvider(); // fixme cache instance @@ -105,7 +114,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement { // get count of all entities of current type (TEntity) to ensure cached result is correct // create query once if it is needed (no need for locking here) - query is static! - var query = _hasIdQuery ?? (_hasIdQuery = UnitOfWork.SqlContext.Query().Where(x => x.Id != 0)); + var query = _hasIdQuery ?? (_hasIdQuery = AmbientScope.SqlContext.Query().Where(x => x.Id != 0)); return PerformCount(query); }); } @@ -132,8 +141,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement // create the cache policy using IsolatedCache which is either global // or scoped depending on the repository cache mode for the current scope - var scope = UnitOfWork.Scope; - switch (scope.RepositoryCacheMode) + switch (AmbientScope.RepositoryCacheMode) { case RepositoryCacheMode.Default: _cachePolicy = CreateCachePolicy(IsolatedCache); @@ -141,7 +149,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement case RepositoryCacheMode.Scoped: _cachePolicy = CreateCachePolicy(IsolatedCache); var globalIsolatedCache = GetIsolatedCache(GlobalCache.IsolatedRuntimeCache); - _cachePolicy = _cachePolicy.Scoped(globalIsolatedCache, scope); + _cachePolicy = _cachePolicy.Scoped(globalIsolatedCache, AmbientScope); break; case RepositoryCacheMode.None: _cachePolicy = NoCacheRepositoryCachePolicy.Instance; diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/ServerRegistrationRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/ServerRegistrationRepository.cs index 483d1049e3..232f8cd414 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/ServerRegistrationRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/ServerRegistrationRepository.cs @@ -8,15 +8,15 @@ using Umbraco.Core.Models; using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence.Factories; using Umbraco.Core.Persistence.Querying; -using Umbraco.Core.Persistence.UnitOfWork; +using Umbraco.Core.Scoping; namespace Umbraco.Core.Persistence.Repositories.Implement { internal class ServerRegistrationRepository : NPocoRepositoryBase, IServerRegistrationRepository { // fixme - should we use NoCache instead of CreateDisabledCacheHelper?! - public ServerRegistrationRepository(IScopeUnitOfWork work, ILogger logger) - : base(work, CacheHelper.CreateDisabledCacheHelper(), logger) + public ServerRegistrationRepository(ScopeProvider scopeProvider, ILogger logger) + : base(scopeProvider, CacheHelper.CreateDisabledCacheHelper(), logger) { } protected override IRepositoryCachePolicy CreateCachePolicy(IRuntimeCacheProvider runtimeCache) diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/SimpleGetRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/SimpleGetRepository.cs index 135dc86f63..0e42daea96 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/SimpleGetRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/SimpleGetRepository.cs @@ -3,10 +3,11 @@ using System.Collections.Generic; using System.Linq; using NPoco; using Umbraco.Core.Cache; +using Umbraco.Core.Exceptions; using Umbraco.Core.Logging; using Umbraco.Core.Models.EntityBase; using Umbraco.Core.Persistence.Querying; -using Umbraco.Core.Persistence.UnitOfWork; +using Umbraco.Core.Scoping; namespace Umbraco.Core.Persistence.Repositories.Implement { @@ -17,11 +18,9 @@ namespace Umbraco.Core.Persistence.Repositories.Implement where TEntity : class, IAggregateRoot where TDto: class { - - protected SimpleGetRepository(IScopeUnitOfWork work, CacheHelper cache, ILogger logger) - : base(work, cache, logger) - { - } + protected SimpleGetRepository(ScopeProvider scopeProvider, CacheHelper cache, ILogger logger) + : base(scopeProvider, cache, logger) + { } protected abstract TEntity ConvertToEntity(TDto dto); protected abstract object GetBaseWhereClauseArguments(TId id); @@ -43,8 +42,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement var entity = ConvertToEntity(dto); - var dirtyEntity = entity as Entity; - if (dirtyEntity != null) + if (entity is Entity dirtyEntity) { // reset dirty initial properties (U4-1946) dirtyEntity.ResetDirtyProperties(false); @@ -77,23 +75,21 @@ namespace Umbraco.Core.Persistence.Repositories.Implement protected sealed override IEnumerable GetDeleteClauses() { - throw new NotImplementedException(); + throw new WontImplementException(); } - protected sealed override Guid NodeObjectTypeId - { - get { throw new NotImplementedException(); } - } + protected sealed override Guid NodeObjectTypeId => throw new WontImplementException(); protected sealed override void PersistNewItem(TEntity entity) { - throw new NotImplementedException(); + throw new WontImplementException(); } protected sealed override void PersistUpdatedItem(TEntity entity) { - throw new NotImplementedException(); + throw new WontImplementException(); } + #endregion } } diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/TagRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/TagRepository.cs index 84b81b9fcf..5dd64cdd46 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/TagRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/TagRepository.cs @@ -9,14 +9,14 @@ using Umbraco.Core.Models.EntityBase; using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence.Factories; using Umbraco.Core.Persistence.Querying; -using Umbraco.Core.Persistence.UnitOfWork; +using Umbraco.Core.Scoping; namespace Umbraco.Core.Persistence.Repositories.Implement { internal class TagRepository : NPocoRepositoryBase, ITagRepository { - public TagRepository(IScopeUnitOfWork work, CacheHelper cache, ILogger logger) - : base(work, cache, logger) + public TagRepository(ScopeProvider scopeProvider, CacheHelper cache, ILogger logger) + : base(scopeProvider, cache, logger) { } diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/TaskRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/TaskRepository.cs index cc0fe96bc2..96546d1b03 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/TaskRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/TaskRepository.cs @@ -5,19 +5,20 @@ using LightInject; using NPoco; using Umbraco.Core.Cache; using Umbraco.Core.Composing.CompositionRoots; +using Umbraco.Core.Exceptions; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence.Factories; using Umbraco.Core.Persistence.Querying; -using Umbraco.Core.Persistence.UnitOfWork; +using Umbraco.Core.Scoping; namespace Umbraco.Core.Persistence.Repositories.Implement { internal class TaskRepository : NPocoRepositoryBase, ITaskRepository { - public TaskRepository(IScopeUnitOfWork work, [Inject(RepositoryCompositionRoot.DisabledCache)] CacheHelper cache, ILogger logger) - : base(work, cache, logger) + public TaskRepository(ScopeProvider scopeProvider, [Inject(RepositoryCompositionRoot.DisabledCache)] CacheHelper cache, ILogger logger) + : base(scopeProvider, cache, logger) { } protected override Task PerformGet(int id) @@ -89,10 +90,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement return list; } - protected override Guid NodeObjectTypeId - { - get { throw new NotImplementedException(); } - } + protected override Guid NodeObjectTypeId => throw new WontImplementException(); protected override void PersistNewItem(Task entity) { diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/TaskTypeRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/TaskTypeRepository.cs index 64eb323e70..f8539d2257 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/TaskTypeRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/TaskTypeRepository.cs @@ -10,16 +10,15 @@ using Umbraco.Core.Models; using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence.Factories; using Umbraco.Core.Persistence.Querying; -using Umbraco.Core.Persistence.UnitOfWork; +using Umbraco.Core.Scoping; namespace Umbraco.Core.Persistence.Repositories.Implement { internal class TaskTypeRepository : NPocoRepositoryBase, ITaskTypeRepository { - public TaskTypeRepository(IScopeUnitOfWork work, [Inject(RepositoryCompositionRoot.DisabledCache)] CacheHelper cache, ILogger logger) - : base(work, cache, logger) - { - } + public TaskTypeRepository(ScopeProvider scopeProvider, [Inject(RepositoryCompositionRoot.DisabledCache)] CacheHelper cache, ILogger logger) + : base(scopeProvider, cache, logger) + { } protected override TaskType PerformGet(int id) { diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/TemplateRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/TemplateRepository.cs index 873f205406..23faa72d68 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/TemplateRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/TemplateRepository.cs @@ -13,7 +13,7 @@ using Umbraco.Core.Models.EntityBase; using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence.Factories; using Umbraco.Core.Persistence.Querying; -using Umbraco.Core.Persistence.UnitOfWork; +using Umbraco.Core.Scoping; using Umbraco.Core.Strings; namespace Umbraco.Core.Persistence.Repositories.Implement @@ -29,8 +29,8 @@ namespace Umbraco.Core.Persistence.Repositories.Implement private readonly ViewHelper _viewHelper; private readonly MasterPageHelper _masterPageHelper; - public TemplateRepository(IScopeUnitOfWork work, CacheHelper cache, ILogger logger, IFileSystem masterpageFileSystem, IFileSystem viewFileSystem, ITemplatesSection templateConfig) - : base(work, cache, logger) + public TemplateRepository(ScopeProvider scopeProvider, CacheHelper cache, ILogger logger, IFileSystem masterpageFileSystem, IFileSystem viewFileSystem, ITemplatesSection templateConfig) + : base(scopeProvider, cache, logger) { _masterpagesFileSystem = masterpageFileSystem; _viewsFileSystem = viewFileSystem; diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/UserGroupRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/UserGroupRepository.cs index 2721ec0585..0df01f6a6e 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/UserGroupRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/UserGroupRepository.cs @@ -12,6 +12,7 @@ using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence.Factories; using Umbraco.Core.Persistence.Querying; using Umbraco.Core.Persistence.UnitOfWork; +using Umbraco.Core.Scoping; namespace Umbraco.Core.Persistence.Repositories.Implement { @@ -23,11 +24,11 @@ namespace Umbraco.Core.Persistence.Repositories.Implement private readonly UserGroupWithUsersRepository _userGroupWithUsersRepository; private readonly PermissionRepository _permissionRepository; - public UserGroupRepository(IScopeUnitOfWork work, CacheHelper cacheHelper, ILogger logger) - : base(work, cacheHelper, logger) + public UserGroupRepository(ScopeProvider scopeProvider, CacheHelper cacheHelper, ILogger logger) + : base(scopeProvider, cacheHelper, logger) { - _userGroupWithUsersRepository = new UserGroupWithUsersRepository(this, work, cacheHelper, logger); - _permissionRepository = new PermissionRepository(work, cacheHelper, logger); + _userGroupWithUsersRepository = new UserGroupWithUsersRepository(this, scopeProvider, cacheHelper, logger); + _permissionRepository = new PermissionRepository(scopeProvider, cacheHelper, logger); } public const string GetByAliasCacheKeyPrefix = "UserGroupRepository_GetByAlias_"; @@ -360,8 +361,8 @@ namespace Umbraco.Core.Persistence.Repositories.Implement { private readonly UserGroupRepository _userGroupRepo; - public UserGroupWithUsersRepository(UserGroupRepository userGroupRepo, IScopeUnitOfWork work, CacheHelper cache, ILogger logger) - : base(work, cache, logger) + public UserGroupWithUsersRepository(UserGroupRepository userGroupRepo, ScopeProvider scopeProvider, CacheHelper cache, ILogger logger) + : base(scopeProvider, cache, logger) { _userGroupRepo = userGroupRepo; } diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/UserRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/UserRepository.cs index daf5306ccd..bf862c44b5 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/UserRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/UserRepository.cs @@ -16,6 +16,7 @@ using Umbraco.Core.Persistence.Factories; using Umbraco.Core.Persistence.Mappers; using Umbraco.Core.Persistence.Querying; using Umbraco.Core.Persistence.UnitOfWork; +using Umbraco.Core.Scoping; using Umbraco.Core.Security; namespace Umbraco.Core.Persistence.Repositories.Implement @@ -37,8 +38,8 @@ namespace Umbraco.Core.Persistence.Repositories.Implement /// /// A dictionary specifying the configuration for user passwords. If this is null then no password configuration will be persisted or read. /// - public UserRepository(IScopeUnitOfWork work, CacheHelper cacheHelper, ILogger logger, IMapperCollection mapperCollection) - : base(work, cacheHelper, logger) + public UserRepository(ScopeProvider scopeProvider, CacheHelper cacheHelper, ILogger logger, IMapperCollection mapperCollection) + : base(scopeProvider, cacheHelper, logger) { _mapperCollection = mapperCollection; @@ -49,8 +50,8 @@ namespace Umbraco.Core.Persistence.Repositories.Implement } // for tests - internal UserRepository(IScopeUnitOfWork work, CacheHelper cacheHelper, ILogger logger, IMapperCollection mapperCollection, IDictionary passwordConfig) - : base(work, cacheHelper, logger) + internal UserRepository(ScopeProvider scopeProvider, CacheHelper cacheHelper, ILogger logger, IMapperCollection mapperCollection, IDictionary passwordConfig) + : base(scopeProvider, cacheHelper, logger) { _mapperCollection = mapperCollection; _passwordConfig = passwordConfig; diff --git a/src/Umbraco.Core/Persistence/UnitOfWorkExtensions.cs b/src/Umbraco.Core/Persistence/UnitOfWorkExtensions.cs index 00a72e993a..10e34a2edb 100644 --- a/src/Umbraco.Core/Persistence/UnitOfWorkExtensions.cs +++ b/src/Umbraco.Core/Persistence/UnitOfWorkExtensions.cs @@ -7,19 +7,6 @@ namespace Umbraco.Core.Persistence { internal static class UnitOfWorkExtensions { - public static IPartialViewRepository CreatePartialViewRepository(this IUnitOfWork uow, PartialViewType partialViewType) - { - switch (partialViewType) - { - case PartialViewType.PartialView: - return uow.CreateRepository(); - case PartialViewType.PartialViewMacro: - return uow.CreateRepository(); - default: - throw new ArgumentOutOfRangeException(nameof(partialViewType)); - } - } - public static IEntityContainerRepository CreateContainerRepository(this IUnitOfWork uow, Guid containerObjectType) { if (containerObjectType == Constants.ObjectTypes.DocumentTypeContainer) diff --git a/src/Umbraco.Core/Scoping/IScopeProvider.cs b/src/Umbraco.Core/Scoping/IScopeProvider.cs index 0b34c74df4..c5e11dd020 100644 --- a/src/Umbraco.Core/Scoping/IScopeProvider.cs +++ b/src/Umbraco.Core/Scoping/IScopeProvider.cs @@ -34,7 +34,8 @@ namespace Umbraco.Core.Scoping RepositoryCacheMode repositoryCacheMode = RepositoryCacheMode.Unspecified, IEventDispatcher eventDispatcher = null, bool? scopeFileSystems = null, - bool callContext = false); + bool callContext = false, + bool readOnly = false); // fixme rename to autoComplete + explain the risks! /// /// Creates a detached scope. diff --git a/src/Umbraco.Core/Scoping/ScopeProvider.cs b/src/Umbraco.Core/Scoping/ScopeProvider.cs index 8234f652f2..2bcb954d76 100644 --- a/src/Umbraco.Core/Scoping/ScopeProvider.cs +++ b/src/Umbraco.Core/Scoping/ScopeProvider.cs @@ -374,7 +374,8 @@ namespace Umbraco.Core.Scoping RepositoryCacheMode repositoryCacheMode = RepositoryCacheMode.Unspecified, IEventDispatcher eventDispatcher = null, bool? scopeFileSystems = null, - bool callContext = false) + bool callContext = false, + bool readOnly = false) // fixme { var ambient = AmbientScope; if (ambient == null) diff --git a/src/Umbraco.Core/Services/AuditService.cs b/src/Umbraco.Core/Services/AuditService.cs index 31478b6e00..02b165c988 100644 --- a/src/Umbraco.Core/Services/AuditService.cs +++ b/src/Umbraco.Core/Services/AuditService.cs @@ -4,70 +4,70 @@ using Umbraco.Core.Events; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Persistence.Repositories; -using Umbraco.Core.Persistence.UnitOfWork; +using Umbraco.Core.Scoping; namespace Umbraco.Core.Services { public sealed class AuditService : ScopeRepositoryService, IAuditService { - public AuditService(IScopeUnitOfWorkProvider provider, ILogger logger, IEventMessagesFactory eventMessagesFactory) + private readonly IAuditRepository _auditRepository; + + public AuditService(IScopeProvider provider, ILogger logger, IEventMessagesFactory eventMessagesFactory, + IAuditRepository auditRepository) : base(provider, logger, eventMessagesFactory) - { } + { + _auditRepository = auditRepository; + } public void Add(AuditType type, string comment, int userId, int objectId) { - using (var uow = UowProvider.CreateUnitOfWork()) + using (var scope = ScopeProvider.CreateScope()) { - var repo = uow.CreateRepository(); - repo.Save(new AuditItem(objectId, comment, type, userId)); - uow.Complete(); + _auditRepository.Save(new AuditItem(objectId, comment, type, userId)); + scope.Complete(); } } public IEnumerable GetLogs(int objectId) { - using (var uow = UowProvider.CreateUnitOfWork()) + using (var scope = ScopeProvider.CreateScope()) { - var repo = uow.CreateRepository(); - var result = repo.Get(Query().Where(x => x.Id == objectId)); - uow.Complete(); + var result = _auditRepository.Get(Query().Where(x => x.Id == objectId)); + scope.Complete(); return result; } } public IEnumerable GetUserLogs(int userId, AuditType type, DateTime? sinceDate = null) { - using (var uow = UowProvider.CreateUnitOfWork()) + using (var scope = ScopeProvider.CreateScope()) { - var repo = uow.CreateRepository(); var result = sinceDate.HasValue == false - ? repo.Get(Query().Where(x => x.UserId == userId && x.AuditType == type)) - : repo.Get(Query().Where(x => x.UserId == userId && x.AuditType == type && x.CreateDate >= sinceDate.Value)); - uow.Complete(); + ? _auditRepository.Get(Query().Where(x => x.UserId == userId && x.AuditType == type)) + : _auditRepository.Get(Query().Where(x => x.UserId == userId && x.AuditType == type && x.CreateDate >= sinceDate.Value)); + scope.Complete(); return result; } } public IEnumerable GetLogs(AuditType type, DateTime? sinceDate = null) { - using (var uow = UowProvider.CreateUnitOfWork()) + using (var scope = ScopeProvider.CreateScope()) { - var repo = uow.CreateRepository(); var result = sinceDate.HasValue == false - ? repo.Get(Query().Where(x => x.AuditType == type)) - : repo.Get(Query().Where(x => x.AuditType == type && x.CreateDate >= sinceDate.Value)); - uow.Complete(); + ? _auditRepository.Get(Query().Where(x => x.AuditType == type)) + : _auditRepository.Get(Query().Where(x => x.AuditType == type && x.CreateDate >= sinceDate.Value)); + scope.Complete(); return result; } } public void CleanLogs(int maximumAgeOfLogsInMinutes) { - using (var uow = UowProvider.CreateUnitOfWork()) + using (var scope = ScopeProvider.CreateScope()) { - var repo = uow.CreateRepository(); - repo.CleanLogs(maximumAgeOfLogsInMinutes); - uow.Complete(); + _auditRepository.CleanLogs(maximumAgeOfLogsInMinutes); + scope.Complete(); } } } diff --git a/src/Umbraco.Core/Services/ContentService.cs b/src/Umbraco.Core/Services/ContentService.cs index 33c7600b02..a266ecdc97 100644 --- a/src/Umbraco.Core/Services/ContentService.cs +++ b/src/Umbraco.Core/Services/ContentService.cs @@ -11,25 +11,39 @@ using Umbraco.Core.Models.Membership; using Umbraco.Core.Persistence.DatabaseModelDefinitions; using Umbraco.Core.Persistence.Querying; using Umbraco.Core.Persistence.Repositories; -using Umbraco.Core.Persistence.UnitOfWork; +using Umbraco.Core.Scoping; using Umbraco.Core.Services.Changes; namespace Umbraco.Core.Services { /// - /// Represents the Content Service, which is an easy access to operations involving + /// Implements the content service. /// - public class ContentService : ScopeRepositoryService, IContentService + internal class ContentService : RepositoryService, IContentService { - private readonly MediaFileSystem _mediaFileSystem; + private readonly IDocumentRepository _documentRepository; + private readonly IEntityRepository _entityRepository; + private readonly IAuditRepository _auditRepository; + private readonly IContentTypeRepository _contentTypeRepository; + private readonly IDocumentBlueprintRepository _documentBlueprintRepository; + + private readonly MediaFileSystem _mediaFileSystem; private IQuery _queryNotTrashed; #region Constructors - public ContentService(IScopeUnitOfWorkProvider provider, ILogger logger, IEventMessagesFactory eventMessagesFactory, MediaFileSystem mediaFileSystem) + public ContentService(IScopeProvider provider, ILogger logger, + IEventMessagesFactory eventMessagesFactory, MediaFileSystem mediaFileSystem, + IDocumentRepository documentRepository, IEntityRepository entityRepository, IAuditRepository auditRepository, + IContentTypeRepository contentTypeRepository, IDocumentBlueprintRepository documentBlueprintRepository) : base(provider, logger, eventMessagesFactory) { _mediaFileSystem = mediaFileSystem; + _documentRepository = documentRepository; + _entityRepository = entityRepository; + _auditRepository = auditRepository; + _contentTypeRepository = contentTypeRepository; + _documentBlueprintRepository = documentBlueprintRepository; } #endregion @@ -46,41 +60,37 @@ namespace Umbraco.Core.Services public int CountPublished(string contentTypeAlias = null) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - uow.ReadLock(Constants.Locks.ContentTree); - var repo = uow.CreateRepository(); - return repo.CountPublished(); + scope.ReadLock(Constants.Locks.ContentTree); + return _documentRepository.CountPublished(); } } public int Count(string contentTypeAlias = null) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - uow.ReadLock(Constants.Locks.ContentTree); - var repo = uow.CreateRepository(); - return repo.Count(contentTypeAlias); + scope.ReadLock(Constants.Locks.ContentTree); + return _documentRepository.Count(contentTypeAlias); } } public int CountChildren(int parentId, string contentTypeAlias = null) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - uow.ReadLock(Constants.Locks.ContentTree); - var repo = uow.CreateRepository(); - return repo.CountChildren(parentId, contentTypeAlias); + scope.ReadLock(Constants.Locks.ContentTree); + return _documentRepository.CountChildren(parentId, contentTypeAlias); } } public int CountDescendants(int parentId, string contentTypeAlias = null) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - uow.ReadLock(Constants.Locks.ContentTree); - var repo = uow.CreateRepository(); - return repo.CountDescendants(parentId, contentTypeAlias); + scope.ReadLock(Constants.Locks.ContentTree); + return _documentRepository.CountDescendants(parentId, contentTypeAlias); } } @@ -95,12 +105,11 @@ namespace Umbraco.Core.Services /// public void SetPermissions(EntityPermissionSet permissionSet) { - using (var uow = UowProvider.CreateUnitOfWork()) + using (var scope = ScopeProvider.CreateScope()) { - uow.WriteLock(Constants.Locks.ContentTree); - var repo = uow.CreateRepository(); - repo.ReplaceContentPermissions(permissionSet); - uow.Complete(); + scope.WriteLock(Constants.Locks.ContentTree); + _documentRepository.ReplaceContentPermissions(permissionSet); + scope.Complete(); } } @@ -112,12 +121,11 @@ namespace Umbraco.Core.Services /// public void SetPermission(IContent entity, char permission, IEnumerable groupIds) { - using (var uow = UowProvider.CreateUnitOfWork()) + using (var scope = ScopeProvider.CreateScope()) { - uow.WriteLock(Constants.Locks.ContentTree); - var repo = uow.CreateRepository(); - repo.AssignEntityPermission(entity, permission, groupIds); - uow.Complete(); + scope.WriteLock(Constants.Locks.ContentTree); + _documentRepository.AssignEntityPermission(entity, permission, groupIds); + scope.Complete(); } } @@ -128,11 +136,10 @@ namespace Umbraco.Core.Services /// public EntityPermissionCollection GetPermissions(IContent content) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - uow.ReadLock(Constants.Locks.ContentTree); - var repo = uow.CreateRepository(); - return repo.GetPermissionsForEntity(content.Id); + scope.ReadLock(Constants.Locks.ContentTree); + return _documentRepository.GetPermissionsForEntity(content.Id); } } @@ -182,10 +189,10 @@ namespace Umbraco.Core.Services throw new ArgumentException("No content with that id.", nameof(parentId)); var content = new Content(name, parentId, contentType); - using (var uow = UowProvider.CreateUnitOfWork()) + using (var scope = ScopeProvider.CreateScope()) { - CreateContent(uow, content, parent, userId, false); - uow.Complete(); + CreateContent(scope, content, parent, userId, false); + scope.Complete(); } return content; @@ -211,10 +218,10 @@ namespace Umbraco.Core.Services throw new ArgumentException("No content type with that alias.", nameof(contentTypeAlias)); var content = new Content(name, -1, contentType); - using (var uow = UowProvider.CreateUnitOfWork()) + using (var scope = ScopeProvider.CreateScope()) { - CreateContent(uow, content, null, userId, false); - uow.Complete(); + CreateContent(scope, content, null, userId, false); + scope.Complete(); } return content; @@ -236,7 +243,7 @@ namespace Umbraco.Core.Services { if (parent == null) throw new ArgumentNullException(nameof(parent)); - using (var uow = UowProvider.CreateUnitOfWork()) + using (var scope = ScopeProvider.CreateScope()) { // not locking since not saving anything @@ -245,9 +252,9 @@ namespace Umbraco.Core.Services throw new ArgumentException("No content type with that alias.", nameof(contentTypeAlias)); // causes rollback var content = new Content(name, parent, contentType); - CreateContent(uow, content, parent, userId, false); + CreateContent(scope, content, parent, userId, false); - uow.Complete(); + scope.Complete(); return content; } } @@ -263,10 +270,10 @@ namespace Umbraco.Core.Services /// The content object. public IContent CreateAndSave(string name, int parentId, string contentTypeAlias, int userId = 0) { - using (var uow = UowProvider.CreateUnitOfWork()) + using (var scope = ScopeProvider.CreateScope()) { // locking the content tree secures content types too - uow.WriteLock(Constants.Locks.ContentTree); + scope.WriteLock(Constants.Locks.ContentTree); var contentType = GetContentType(contentTypeAlias); // + locks if (contentType == null) @@ -277,9 +284,9 @@ namespace Umbraco.Core.Services throw new ArgumentException("No content with that id.", nameof(parentId)); // causes rollback var content = parentId > 0 ? new Content(name, parent, contentType) : new Content(name, parentId, contentType); - CreateContent(uow, content, parent, userId, true); + CreateContent(scope, content, parent, userId, true); - uow.Complete(); + scope.Complete(); return content; } } @@ -297,24 +304,24 @@ namespace Umbraco.Core.Services { if (parent == null) throw new ArgumentNullException(nameof(parent)); - using (var uow = UowProvider.CreateUnitOfWork()) + using (var scope = ScopeProvider.CreateScope()) { // locking the content tree secures content types too - uow.WriteLock(Constants.Locks.ContentTree); + scope.WriteLock(Constants.Locks.ContentTree); var contentType = GetContentType(contentTypeAlias); // + locks if (contentType == null) throw new ArgumentException("No content type with that alias.", nameof(contentTypeAlias)); // causes rollback var content = new Content(name, parent, contentType); - CreateContent(uow, content, parent, userId, true); + CreateContent(scope, content, parent, userId, true); - uow.Complete(); + scope.Complete(); return content; } } - private void CreateContent(IScopeUnitOfWork uow, Content content, IContent parent, int userId, bool withIdentity) + private void CreateContent(IScope scope, Content content, IContent parent, int userId, bool withIdentity) { // NOTE: I really hate the notion of these Creating/Created events - they are so inconsistent, I've only just found // out that in these 'WithIdentity' methods, the Saving/Saved events were not fired, wtf. Anyways, they're added now. @@ -322,7 +329,7 @@ namespace Umbraco.Core.Services ? new NewEventArgs(content, content.ContentType.Alias, parent) : new NewEventArgs(content, content.ContentType.Alias, -1); - if (uow.Events.DispatchCancelable(Creating, this, newArgs)) + if (scope.Events.DispatchCancelable(Creating, this, newArgs)) { content.WasCancelled = true; return; @@ -334,28 +341,25 @@ namespace Umbraco.Core.Services if (withIdentity) { var saveEventArgs = new SaveEventArgs(content); - if (uow.Events.DispatchCancelable(Saving, this, saveEventArgs, "Saving")) + if (scope.Events.DispatchCancelable(Saving, this, saveEventArgs, "Saving")) { content.WasCancelled = true; return; } - var repo = uow.CreateRepository(); - repo.Save(content); - - uow.Flush(); // need everything so we can serialize + _documentRepository.Save(content); saveEventArgs.CanCancel = false; - uow.Events.Dispatch(Saved, this, saveEventArgs, "Saved"); - uow.Events.Dispatch(TreeChanged, this, new TreeChange(content, TreeChangeTypes.RefreshNode).ToEventArgs()); + scope.Events.Dispatch(Saved, this, saveEventArgs, "Saved"); + scope.Events.Dispatch(TreeChanged, this, new TreeChange(content, TreeChangeTypes.RefreshNode).ToEventArgs()); } - uow.Events.Dispatch(Created, this, new NewEventArgs(content, false, content.ContentType.Alias, parent)); + scope.Events.Dispatch(Created, this, new NewEventArgs(content, false, content.ContentType.Alias, parent)); if (withIdentity == false) return; - Audit(uow, AuditType.New, $"Content '{content.Name}' was created with Id {content.Id}", content.CreatorId, content.Id); + Audit(AuditType.New, $"Content '{content.Name}' was created with Id {content.Id}", content.CreatorId, content.Id); } #endregion @@ -369,11 +373,10 @@ namespace Umbraco.Core.Services /// public IContent GetById(int id) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - uow.ReadLock(Constants.Locks.ContentTree); - var repository = uow.CreateRepository(); - return repository.Get(id); + scope.ReadLock(Constants.Locks.ContentTree); + return _documentRepository.Get(id); } } @@ -387,11 +390,10 @@ namespace Umbraco.Core.Services var idsA = ids.ToArray(); if (idsA.Length == 0) return Enumerable.Empty(); - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - uow.ReadLock(Constants.Locks.ContentTree); - var repository = uow.CreateRepository(); - var items = repository.GetMany(idsA); + scope.ReadLock(Constants.Locks.ContentTree); + var items = _documentRepository.GetMany(idsA); var index = items.ToDictionary(x => x.Id, x => x); @@ -406,11 +408,10 @@ namespace Umbraco.Core.Services /// public IContent GetById(Guid key) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - uow.ReadLock(Constants.Locks.ContentTree); - var repository = uow.CreateRepository(); - return repository.Get(key); + scope.ReadLock(Constants.Locks.ContentTree); + return _documentRepository.Get(key); } } @@ -424,11 +425,10 @@ namespace Umbraco.Core.Services var idsA = ids.ToArray(); if (idsA.Length == 0) return Enumerable.Empty(); - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - uow.ReadLock(Constants.Locks.ContentTree); - var repository = uow.CreateRepository(); - var items = repository.GetMany(idsA); + scope.ReadLock(Constants.Locks.ContentTree); + var items = _documentRepository.GetMany(idsA); var index = items.ToDictionary(x => x.Key, x => x); @@ -443,23 +443,21 @@ namespace Umbraco.Core.Services /// An Enumerable list of objects public IEnumerable GetByType(int id) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - uow.ReadLock(Constants.Locks.ContentTree); - var repository = uow.CreateRepository(); + scope.ReadLock(Constants.Locks.ContentTree); var query = Query().Where(x => x.ContentTypeId == id); - return repository.Get(query); + return _documentRepository.Get(query); } } internal IEnumerable GetPublishedContentOfContentType(int id) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - uow.ReadLock(Constants.Locks.ContentTree); - var repository = uow.CreateRepository(); + scope.ReadLock(Constants.Locks.ContentTree); var query = Query().Where(x => x.ContentTypeId == id); - return repository.Get(query); + return _documentRepository.Get(query); } } @@ -471,12 +469,11 @@ namespace Umbraco.Core.Services /// Contrary to most methods, this method filters out trashed content items. public IEnumerable GetByLevel(int level) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - uow.ReadLock(Constants.Locks.ContentTree); - var repository = uow.CreateRepository(); + scope.ReadLock(Constants.Locks.ContentTree); var query = Query().Where(x => x.Level == level && x.Trashed == false); - return repository.Get(query); + return _documentRepository.Get(query); } } @@ -487,11 +484,10 @@ namespace Umbraco.Core.Services /// An item public IContent GetVersion(int versionId) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - uow.ReadLock(Constants.Locks.ContentTree); - var repository = uow.CreateRepository(); - return repository.GetVersion(versionId); + scope.ReadLock(Constants.Locks.ContentTree); + return _documentRepository.GetVersion(versionId); } } @@ -502,11 +498,10 @@ namespace Umbraco.Core.Services /// An Enumerable list of objects public IEnumerable GetVersions(int id) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - uow.ReadLock(Constants.Locks.ContentTree); - var repository = uow.CreateRepository(); - return repository.GetAllVersions(id); + scope.ReadLock(Constants.Locks.ContentTree); + return _documentRepository.GetAllVersions(id); } } @@ -518,10 +513,9 @@ namespace Umbraco.Core.Services /// public IEnumerable GetVersionIds(int id, int maxRows) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - var repository = uow.CreateRepository(); - return repository.GetVersionIds(id, maxRows); + return _documentRepository.GetVersionIds(id, maxRows); } } @@ -553,11 +547,10 @@ namespace Umbraco.Core.Services if (ids.Any() == false) return new List(); - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - uow.ReadLock(Constants.Locks.ContentTree); - var repository = uow.CreateRepository(); - return repository.GetMany(ids); + scope.ReadLock(Constants.Locks.ContentTree); + return _documentRepository.GetMany(ids); } } @@ -568,12 +561,11 @@ namespace Umbraco.Core.Services /// An Enumerable list of objects public IEnumerable GetChildren(int id) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - uow.ReadLock(Constants.Locks.ContentTree); - var repository = uow.CreateRepository(); + scope.ReadLock(Constants.Locks.ContentTree); var query = Query().Where(x => x.ParentId == id); - return repository.Get(query).OrderBy(x => x.SortOrder); + return _documentRepository.Get(query).OrderBy(x => x.SortOrder); } } @@ -584,12 +576,11 @@ namespace Umbraco.Core.Services /// An Enumerable list of published objects public IEnumerable GetPublishedChildren(int id) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - uow.ReadLock(Constants.Locks.ContentTree); - var repository = uow.CreateRepository(); + scope.ReadLock(Constants.Locks.ContentTree); var query = Query().Where(x => x.ParentId == id && x.Published); - return repository.Get(query).OrderBy(x => x.SortOrder); + return _documentRepository.Get(query).OrderBy(x => x.SortOrder); } } @@ -607,14 +598,13 @@ namespace Umbraco.Core.Services public IEnumerable GetPagedChildren(int id, long pageIndex, int pageSize, out long totalChildren, string orderBy, Direction orderDirection, string filter = "") { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - uow.ReadLock(Constants.Locks.ContentTree); - var repository = uow.CreateRepository(); + scope.ReadLock(Constants.Locks.ContentTree); var filterQuery = filter.IsNullOrWhiteSpace() ? null : Query().Where(x => x.Name.Contains(filter)); - // fixme nesting uow?! + return GetPagedChildren(id, pageIndex, pageSize, out totalChildren, orderBy, orderDirection, true, filterQuery); } } @@ -637,16 +627,15 @@ namespace Umbraco.Core.Services if (pageIndex < 0) throw new ArgumentOutOfRangeException(nameof(pageIndex)); if (pageSize <= 0) throw new ArgumentOutOfRangeException(nameof(pageSize)); - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - uow.ReadLock(Constants.Locks.ContentTree); - var repository = uow.CreateRepository(); + scope.ReadLock(Constants.Locks.ContentTree); var query = Query(); //if the id is System Root, then just get all - NO! does not make sense! //if (id != Constants.System.Root) query.Where(x => x.ParentId == id); - return repository.GetPage(query, pageIndex, pageSize, out totalChildren, orderBy, orderDirection, orderBySystemField, filter); + return _documentRepository.GetPage(query, pageIndex, pageSize, out totalChildren, orderBy, orderDirection, orderBySystemField, filter); } } @@ -663,13 +652,13 @@ namespace Umbraco.Core.Services /// An Enumerable list of objects public IEnumerable GetPagedDescendants(int id, long pageIndex, int pageSize, out long totalChildren, string orderBy = "Path", Direction orderDirection = Direction.Ascending, string filter = "") { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - uow.ReadLock(Constants.Locks.ContentTree); + scope.ReadLock(Constants.Locks.ContentTree); var filterQuery = filter.IsNullOrWhiteSpace() ? null : Query().Where(x => x.Name.Contains(filter)); - // fixme nesting uow? + return GetPagedDescendants(id, pageIndex, pageSize, out totalChildren, orderBy, orderDirection, true, filterQuery); } } @@ -691,17 +680,15 @@ namespace Umbraco.Core.Services if (pageIndex < 0) throw new ArgumentOutOfRangeException(nameof(pageIndex)); if (pageSize <= 0) throw new ArgumentOutOfRangeException(nameof(pageSize)); - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - uow.ReadLock(Constants.Locks.ContentTree); - var repository = uow.CreateRepository(); + scope.ReadLock(Constants.Locks.ContentTree); var query = Query(); //if the id is System Root, then just get all if (id != Constants.System.Root) { - var entityRepository = uow.CreateRepository(); - var contentPath = entityRepository.GetAllPaths(Constants.ObjectTypes.Document, id).ToArray(); + var contentPath = _entityRepository.GetAllPaths(Constants.ObjectTypes.Document, id).ToArray(); if (contentPath.Length == 0) { totalChildren = 0; @@ -709,7 +696,7 @@ namespace Umbraco.Core.Services } query.Where(x => x.Path.SqlStartsWith($"{contentPath[0]},", TextColumnType.NVarchar)); } - return repository.GetPage(query, pageIndex, pageSize, out totalChildren, orderBy, orderDirection, orderBySystemField, filter); + return _documentRepository.GetPage(query, pageIndex, pageSize, out totalChildren, orderBy, orderDirection, orderBySystemField, filter); } } @@ -721,12 +708,11 @@ namespace Umbraco.Core.Services /// An Enumerable list of objects public IEnumerable GetChildren(int parentId, string name) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - uow.ReadLock(Constants.Locks.ContentTree); - var repository = uow.CreateRepository(); + scope.ReadLock(Constants.Locks.ContentTree); var query = Query().Where(x => x.ParentId == parentId && x.Name.Contains(name)); - return repository.Get(query); + return _documentRepository.Get(query); } } @@ -737,19 +723,18 @@ namespace Umbraco.Core.Services /// An Enumerable list of objects public IEnumerable GetDescendants(int id) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - uow.ReadLock(Constants.Locks.ContentTree); - var repository = uow.CreateRepository(); + scope.ReadLock(Constants.Locks.ContentTree); var content = GetById(id); if (content == null) { - uow.Complete(); // else causes rollback + scope.Complete(); // else causes rollback return Enumerable.Empty(); } var pathMatch = content.Path + ","; var query = Query().Where(x => x.Id != content.Id && x.Path.StartsWith(pathMatch)); - return repository.Get(query); + return _documentRepository.Get(query); } } @@ -760,13 +745,12 @@ namespace Umbraco.Core.Services /// An Enumerable list of objects public IEnumerable GetDescendants(IContent content) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - uow.ReadLock(Constants.Locks.ContentTree); - var repository = uow.CreateRepository(); + scope.ReadLock(Constants.Locks.ContentTree); var pathMatch = content.Path + ","; var query = Query().Where(x => x.Id != content.Id && x.Path.StartsWith(pathMatch)); - return repository.Get(query); + return _documentRepository.Get(query); } } @@ -801,12 +785,11 @@ namespace Umbraco.Core.Services /// An Enumerable list of objects public IEnumerable GetRootContent() { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - uow.ReadLock(Constants.Locks.ContentTree); - var repository = uow.CreateRepository(); + scope.ReadLock(Constants.Locks.ContentTree); var query = Query().Where(x => x.ParentId == Constants.System.Root); - return repository.Get(query); + return _documentRepository.Get(query); } } @@ -816,11 +799,10 @@ namespace Umbraco.Core.Services /// internal IEnumerable GetAllPublished() { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - uow.ReadLock(Constants.Locks.ContentTree); - var repository = uow.CreateRepository(); - return repository.Get(QueryNotTrashed); + scope.ReadLock(Constants.Locks.ContentTree); + return _documentRepository.Get(QueryNotTrashed); } } @@ -830,53 +812,40 @@ namespace Umbraco.Core.Services /// An Enumerable list of objects public IEnumerable GetContentForExpiration() { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - uow.ReadLock(Constants.Locks.ContentTree); - return GetContentForExpiration(uow); + scope.ReadLock(Constants.Locks.ContentTree); + var query = Query().Where(x => x.Published && x.ExpireDate <= DateTime.Now); + return _documentRepository.Get(query); } } - private IEnumerable GetContentForExpiration(IScopeUnitOfWork uow) - { - var repository = uow.CreateRepository(); - var query = Query().Where(x => x.Published && x.ExpireDate <= DateTime.Now); - return repository.Get(query); - } - /// /// Gets a collection of objects, which has a release date less than or equal to today. /// /// An Enumerable list of objects public IEnumerable GetContentForRelease() { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - uow.ReadLock(Constants.Locks.ContentTree); - return GetContentForRelease(uow); + scope.ReadLock(Constants.Locks.ContentTree); + var query = Query().Where(x => x.Published == false && x.ReleaseDate <= DateTime.Now); + return _documentRepository.Get(query); } } - private IEnumerable GetContentForRelease(IScopeUnitOfWork uow) - { - var repository = uow.CreateRepository(); - var query = Query().Where(x => x.Published == false && x.ReleaseDate <= DateTime.Now); - return repository.Get(query); - } - /// /// Gets a collection of an objects, which resides in the Recycle Bin /// /// An Enumerable list of objects public IEnumerable GetContentInRecycleBin() { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - uow.ReadLock(Constants.Locks.ContentTree); - var repository = uow.CreateRepository(); + scope.ReadLock(Constants.Locks.ContentTree); var bin = $"{Constants.System.Root},{Constants.System.RecycleBinContent},"; var query = Query().Where(x => x.Path.StartsWith(bin)); - return repository.Get(query); + return _documentRepository.Get(query); } } @@ -908,11 +877,10 @@ namespace Umbraco.Core.Services public bool IsPathPublished(IContent content) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - uow.ReadLock(Constants.Locks.ContentTree); - var repo = uow.CreateRepository(); - return repo.IsPathPublished(content); + scope.ReadLock(Constants.Locks.ContentTree); + return _documentRepository.IsPathPublished(content); } } @@ -931,12 +899,12 @@ namespace Umbraco.Core.Services var evtMsgs = EventMessagesFactory.Get(); - using (var uow = UowProvider.CreateUnitOfWork()) + using (var scope = ScopeProvider.CreateScope()) { var saveEventArgs = new SaveEventArgs(content, evtMsgs); - if (raiseEvents && uow.Events.DispatchCancelable(Saving, this, saveEventArgs, "Saving")) + if (raiseEvents && scope.Events.DispatchCancelable(Saving, this, saveEventArgs, "Saving")) { - uow.Complete(); + scope.Complete(); return OperationResult.Cancel(evtMsgs); } @@ -947,24 +915,23 @@ namespace Umbraco.Core.Services var isNew = content.IsNewEntity(); - uow.WriteLock(Constants.Locks.ContentTree); + scope.WriteLock(Constants.Locks.ContentTree); - var repository = uow.CreateRepository(); if (content.HasIdentity == false) content.CreatorId = userId; content.WriterId = userId; - repository.Save(content); + _documentRepository.Save(content); if (raiseEvents) { saveEventArgs.CanCancel = false; - uow.Events.Dispatch(Saved, this, saveEventArgs, "Saved"); + scope.Events.Dispatch(Saved, this, saveEventArgs, "Saved"); } var changeType = isNew ? TreeChangeTypes.RefreshBranch : TreeChangeTypes.RefreshNode; - uow.Events.Dispatch(TreeChanged, this, new TreeChange(content, changeType).ToEventArgs()); - Audit(uow, AuditType.Save, "Save Content performed by user", userId, content.Id); - uow.Complete(); + scope.Events.Dispatch(TreeChanged, this, new TreeChange(content, changeType).ToEventArgs()); + Audit(AuditType.Save, "Save Content performed by user", userId, content.Id); + scope.Complete(); } return OperationResult.Succeed(evtMsgs); @@ -976,38 +943,37 @@ namespace Umbraco.Core.Services var evtMsgs = EventMessagesFactory.Get(); var contentsA = contents.ToArray(); - using (var uow = UowProvider.CreateUnitOfWork()) + using (var scope = ScopeProvider.CreateScope()) { var saveEventArgs = new SaveEventArgs(contentsA, evtMsgs); - if (raiseEvents && uow.Events.DispatchCancelable(Saving, this, saveEventArgs, "Saving")) + if (raiseEvents && scope.Events.DispatchCancelable(Saving, this, saveEventArgs, "Saving")) { - uow.Complete(); + scope.Complete(); return OperationResult.Cancel(evtMsgs); } var treeChanges = contentsA.Select(x => new TreeChange(x, x.IsNewEntity() ? TreeChangeTypes.RefreshBranch : TreeChangeTypes.RefreshNode)); - uow.WriteLock(Constants.Locks.ContentTree); - var repository = uow.CreateRepository(); + scope.WriteLock(Constants.Locks.ContentTree); foreach (var content in contentsA) { if (content.HasIdentity == false) content.CreatorId = userId; content.WriterId = userId; - repository.Save(content); + _documentRepository.Save(content); } if (raiseEvents) { saveEventArgs.CanCancel = false; - uow.Events.Dispatch(Saved, this, saveEventArgs, "Saved"); + scope.Events.Dispatch(Saved, this, saveEventArgs, "Saved"); } - uow.Events.Dispatch(TreeChanged, this, treeChanges.ToEventArgs()); - Audit(uow, AuditType.Save, "Bulk Save content performed by user", userId == -1 ? 0 : userId, Constants.System.Root); + scope.Events.Dispatch(TreeChanged, this, treeChanges.ToEventArgs()); + Audit(AuditType.Save, "Bulk Save content performed by user", userId == -1 ? 0 : userId, Constants.System.Root); - uow.Complete(); + scope.Complete(); } return OperationResult.Succeed(evtMsgs); @@ -1027,12 +993,12 @@ namespace Umbraco.Core.Services return new PublishResult(PublishResultType.SuccessAlready, evtMsgs, content); } - using (var uow = UowProvider.CreateUnitOfWork()) + using (var scope = ScopeProvider.CreateScope()) { var saveEventArgs = new SaveEventArgs(content, evtMsgs); - if (raiseEvents && uow.Events.DispatchCancelable(Saving, this, saveEventArgs, "Saving")) + if (raiseEvents && scope.Events.DispatchCancelable(Saving, this, saveEventArgs, "Saving")) { - uow.Complete(); + scope.Complete(); return new PublishResult(PublishResultType.FailedCancelledByEvent, evtMsgs, content); } @@ -1040,31 +1006,30 @@ namespace Umbraco.Core.Services var changeType = isNew ? TreeChangeTypes.RefreshBranch : TreeChangeTypes.RefreshNode; var previouslyPublished = content.HasIdentity && content.Published; - uow.WriteLock(Constants.Locks.ContentTree); - var repository = uow.CreateRepository(); + scope.WriteLock(Constants.Locks.ContentTree); // ensure that the document can be published, and publish // handling events, business rules, etc - result = StrategyCanPublish(uow, content, userId, /*checkPath:*/ true, evtMsgs); + result = StrategyCanPublish(scope, content, userId, /*checkPath:*/ true, evtMsgs); if (result.Success) - result = StrategyPublish(uow, content, /*canPublish:*/ true, userId, evtMsgs); + result = StrategyPublish(scope, content, /*canPublish:*/ true, userId, evtMsgs); // save - always, even if not publishing (this is SaveAndPublish) if (content.HasIdentity == false) content.CreatorId = userId; content.WriterId = userId; - repository.Save(content); + _documentRepository.Save(content); if (raiseEvents) // always { saveEventArgs.CanCancel = false; - uow.Events.Dispatch(Saved, this, saveEventArgs, "Saved"); + scope.Events.Dispatch(Saved, this, saveEventArgs, "Saved"); } if (result.Success == false) { - uow.Events.Dispatch(TreeChanged, this, new TreeChange(content, changeType).ToEventArgs()); + scope.Events.Dispatch(TreeChanged, this, new TreeChange(content, changeType).ToEventArgs()); return result; } @@ -1072,22 +1037,22 @@ namespace Umbraco.Core.Services changeType = TreeChangeTypes.RefreshBranch; // whole branch // invalidate the node/branch - uow.Events.Dispatch(TreeChanged, this, new TreeChange(content, changeType).ToEventArgs()); + scope.Events.Dispatch(TreeChanged, this, new TreeChange(content, changeType).ToEventArgs()); - uow.Events.Dispatch(Published, this, new PublishEventArgs(content, false, false), "Published"); + scope.Events.Dispatch(Published, this, new PublishEventArgs(content, false, false), "Published"); // if was not published and now is... descendants that were 'published' (but // had an unpublished ancestor) are 're-published' ie not explicitely published // but back as 'published' nevertheless if (isNew == false && previouslyPublished == false && HasChildren(content.Id)) { - var descendants = GetPublishedDescendantsLocked(uow, repository, content).ToArray(); - uow.Events.Dispatch(Published, this, new PublishEventArgs(descendants, false, false), "Published"); + var descendants = GetPublishedDescendantsLocked(content).ToArray(); + scope.Events.Dispatch(Published, this, new PublishEventArgs(descendants, false, false), "Published"); } - Audit(uow, AuditType.Publish, "Save and Publish performed by user", userId, content.Id); + Audit(AuditType.Publish, "Save and Publish performed by user", userId, content.Id); - uow.Complete(); + scope.Complete(); } return result; @@ -1098,35 +1063,34 @@ namespace Umbraco.Core.Services { var evtMsgs = EventMessagesFactory.Get(); - using (var uow = UowProvider.CreateUnitOfWork()) + using (var scope = ScopeProvider.CreateScope()) { - uow.WriteLock(Constants.Locks.ContentTree); - var repository = uow.CreateRepository(); + scope.WriteLock(Constants.Locks.ContentTree); var newest = GetById(content.Id); // ensure we have the newest version if (content.VersionId != newest.VersionId) // but use the original object if it's already the newest version content = newest; if (content.Published == false) { - uow.Complete(); + scope.Complete(); return new PublishResult(PublishResultType.SuccessAlready, evtMsgs, content); // already unpublished } // strategy // fixme should we still complete the uow? don't want to rollback here! - var attempt = StrategyCanUnpublish(uow, content, userId, evtMsgs); + var attempt = StrategyCanUnpublish(scope, content, userId, evtMsgs); if (attempt.Success == false) return attempt; // causes rollback - attempt = StrategyUnpublish(uow, content, true, userId, evtMsgs); + attempt = StrategyUnpublish(scope, content, true, userId, evtMsgs); if (attempt.Success == false) return attempt; // causes rollback content.WriterId = userId; - repository.Save(content); + _documentRepository.Save(content); - uow.Events.Dispatch(UnPublished, this, new PublishEventArgs(content, false, false), "UnPublished"); - uow.Events.Dispatch(TreeChanged, this, new TreeChange(content, TreeChangeTypes.RefreshBranch).ToEventArgs()); - Audit(uow, AuditType.UnPublish, "UnPublish performed by user", userId, content.Id); + scope.Events.Dispatch(UnPublished, this, new PublishEventArgs(content, false, false), "UnPublished"); + scope.Events.Dispatch(TreeChanged, this, new TreeChange(content, TreeChangeTypes.RefreshBranch).ToEventArgs()); + Audit(AuditType.UnPublish, "UnPublish performed by user", userId, content.Id); - uow.Complete(); + scope.Complete(); } return new PublishResult(PublishResultType.Success, evtMsgs, content); @@ -1135,11 +1099,11 @@ namespace Umbraco.Core.Services /// public IEnumerable PerformScheduledPublish() { - using (var uow = UowProvider.CreateUnitOfWork()) + using (var scope = ScopeProvider.CreateScope()) { - uow.WriteLock(Constants.Locks.ContentTree); + scope.WriteLock(Constants.Locks.ContentTree); - foreach (var d in GetContentForRelease(uow)) + foreach (var d in GetContentForRelease()) { PublishResult result; try @@ -1157,7 +1121,7 @@ namespace Umbraco.Core.Services } yield return result; } - foreach (var d in GetContentForExpiration(uow)) + foreach (var d in GetContentForExpiration()) { try { @@ -1173,7 +1137,7 @@ namespace Umbraco.Core.Services } } - uow.Complete(); + scope.Complete(); } } @@ -1194,10 +1158,9 @@ namespace Umbraco.Core.Services var results = new List(); var publishedDocuments = new List(); - using (var uow = UowProvider.CreateUnitOfWork()) + using (var scope = ScopeProvider.CreateScope()) { - uow.WriteLock(Constants.Locks.ContentTree); - var repository = uow.CreateRepository(); + scope.WriteLock(Constants.Locks.ContentTree); // fixme events?! @@ -1209,7 +1172,7 @@ namespace Umbraco.Core.Services throw new InvalidOperationException("Do not publish values when publishing branches."); // deal with the branch root - if it fails, abort - var result = SaveAndPublishBranchOne(document, repository, uow, editing, publishValues, true, publishedDocuments, evtMsgs, userId); + var result = SaveAndPublishBranchOne(scope, document, editing, publishValues, true, publishedDocuments, evtMsgs, userId); results.Add(result); if (!result.Success) return results; @@ -1229,7 +1192,7 @@ namespace Umbraco.Core.Services // no need to check path here, // 1. because we know the parent is path-published (we just published it) // 2. because it would not work as nothing's been written out to the db until the uow completes - result = SaveAndPublishBranchOne(d, repository, uow, editing, publishValues, false, publishedDocuments, evtMsgs, userId); + result = SaveAndPublishBranchOne(scope, d, editing, publishValues, false, publishedDocuments, evtMsgs, userId); results.Add(result); if (result.Success) continue; @@ -1237,18 +1200,17 @@ namespace Umbraco.Core.Services exclude.Add(d.Id); } - uow.Events.Dispatch(TreeChanged, this, new TreeChange(document, TreeChangeTypes.RefreshBranch).ToEventArgs()); - uow.Events.Dispatch(Published, this, new PublishEventArgs(publishedDocuments, false, false), "Published"); - Audit(uow, AuditType.Publish, "SaveAndPublishBranch performed by user", userId, document.Id); + scope.Events.Dispatch(TreeChanged, this, new TreeChange(document, TreeChangeTypes.RefreshBranch).ToEventArgs()); + scope.Events.Dispatch(Published, this, new PublishEventArgs(publishedDocuments, false, false), "Published"); + Audit(AuditType.Publish, "SaveAndPublishBranch performed by user", userId, document.Id); - uow.Complete(); + scope.Complete(); } return results; } - private PublishResult SaveAndPublishBranchOne(IContent document, - IDocumentRepository repository, IScopeUnitOfWork uow, + private PublishResult SaveAndPublishBranchOne(IScope scope, IContent document, Func editing, Func publishValues, bool checkPath, List publishedDocuments, @@ -1264,18 +1226,18 @@ namespace Umbraco.Core.Services return new PublishResult(PublishResultType.FailedContentInvalid, evtMsgs, document); // check if we can publish - var result = StrategyCanPublish(uow, document, userId, checkPath, evtMsgs); + var result = StrategyCanPublish(scope, document, userId, checkPath, evtMsgs); if (!result.Success) return result; // publish - should be successful - var publishResult = StrategyPublish(uow, document, /*canPublish:*/ true, userId, evtMsgs); + var publishResult = StrategyPublish(scope, document, /*canPublish:*/ true, userId, evtMsgs); if (!publishResult.Success) throw new Exception("oops: failed to publish."); // save document.WriterId = userId; - repository.Save(document); + _documentRepository.Save(document); publishedDocuments.Add(document); return publishResult; } @@ -1289,36 +1251,35 @@ namespace Umbraco.Core.Services { var evtMsgs = EventMessagesFactory.Get(); - using (var uow = UowProvider.CreateUnitOfWork()) + using (var scope = ScopeProvider.CreateScope()) { var deleteEventArgs = new DeleteEventArgs(content, evtMsgs); - if (uow.Events.DispatchCancelable(Deleting, this, deleteEventArgs)) + if (scope.Events.DispatchCancelable(Deleting, this, deleteEventArgs)) { - uow.Complete(); + scope.Complete(); return OperationResult.Cancel(evtMsgs); } - uow.WriteLock(Constants.Locks.ContentTree); - var repository = uow.CreateRepository(); + scope.WriteLock(Constants.Locks.ContentTree); // if it's not trashed yet, and published, we should unpublish // but... UnPublishing event makes no sense (not going to cancel?) and no need to save // just raise the event if (content.Trashed == false && content.Published) - uow.Events.Dispatch(UnPublished, this, new PublishEventArgs(content, false, false), "UnPublished"); + scope.Events.Dispatch(UnPublished, this, new PublishEventArgs(content, false, false), "UnPublished"); - DeleteLocked(uow, repository, content); + DeleteLocked(scope, content); - uow.Events.Dispatch(TreeChanged, this, new TreeChange(content, TreeChangeTypes.Remove).ToEventArgs()); - Audit(uow, AuditType.Delete, "Delete Content performed by user", userId, content.Id); + scope.Events.Dispatch(TreeChanged, this, new TreeChange(content, TreeChangeTypes.Remove).ToEventArgs()); + Audit(AuditType.Delete, "Delete Content performed by user", userId, content.Id); - uow.Complete(); + scope.Complete(); } return OperationResult.Succeed(evtMsgs); } - private void DeleteLocked(IScopeUnitOfWork uow, IDocumentRepository repository, IContent content) + private void DeleteLocked(IScope scope, IContent content) { // then recursively delete descendants, bottom-up // just repository.Delete + an event @@ -1339,9 +1300,9 @@ namespace Umbraco.Core.Services c = stack.Pop(); level = c.Level; - repository.Delete(c); + _documentRepository.Delete(c); var args = new DeleteEventArgs(c, false); // raise event & get flagged files - uow.Events.Dispatch(Deleted, this, args); + scope.Events.Dispatch(Deleted, this, args); // fixme not going to work, do it differently _mediaFileSystem.DeleteFiles(args.MediaFilesToDelete, // remove flagged files @@ -1364,24 +1325,23 @@ namespace Umbraco.Core.Services /// Optional Id of the User deleting versions of a Content object public void DeleteVersions(int id, DateTime versionDate, int userId = 0) { - using (var uow = UowProvider.CreateUnitOfWork()) + using (var scope = ScopeProvider.CreateScope()) { var deleteRevisionsEventArgs = new DeleteRevisionsEventArgs(id, dateToRetain: versionDate); - if (uow.Events.DispatchCancelable(DeletingVersions, this, deleteRevisionsEventArgs)) + if (scope.Events.DispatchCancelable(DeletingVersions, this, deleteRevisionsEventArgs)) { - uow.Complete(); + scope.Complete(); return; } - uow.WriteLock(Constants.Locks.ContentTree); - var repository = uow.CreateRepository(); - repository.DeleteVersions(id, versionDate); + scope.WriteLock(Constants.Locks.ContentTree); + _documentRepository.DeleteVersions(id, versionDate); deleteRevisionsEventArgs.CanCancel = false; - uow.Events.Dispatch(DeletedVersions, this, deleteRevisionsEventArgs); - Audit(uow, AuditType.Delete, "Delete Content by version date performed by user", userId, Constants.System.Root); + scope.Events.Dispatch(DeletedVersions, this, deleteRevisionsEventArgs); + Audit(AuditType.Delete, "Delete Content by version date performed by user", userId, Constants.System.Root); - uow.Complete(); + scope.Complete(); } } @@ -1395,11 +1355,11 @@ namespace Umbraco.Core.Services /// Optional Id of the User deleting versions of a Content object public void DeleteVersion(int id, int versionId, bool deletePriorVersions, int userId = 0) { - using (var uow = UowProvider.CreateUnitOfWork()) + using (var scope = ScopeProvider.CreateScope()) { - if (uow.Events.DispatchCancelable(DeletingVersions, this, new DeleteRevisionsEventArgs(id, /*specificVersion:*/ versionId))) + if (scope.Events.DispatchCancelable(DeletingVersions, this, new DeleteRevisionsEventArgs(id, /*specificVersion:*/ versionId))) { - uow.Complete(); + scope.Complete(); return; } @@ -1410,16 +1370,15 @@ namespace Umbraco.Core.Services DeleteVersions(id, content.UpdateDate, userId); } - uow.WriteLock(Constants.Locks.ContentTree); - var repository = uow.CreateRepository(); - var c = repository.Get(id); + scope.WriteLock(Constants.Locks.ContentTree); + var c = _documentRepository.Get(id); if (c.VersionId != versionId) // don't delete the current version - repository.DeleteVersion(versionId); + _documentRepository.DeleteVersion(versionId); - uow.Events.Dispatch(DeletedVersions, this, new DeleteRevisionsEventArgs(id, false,/* specificVersion:*/ versionId)); - Audit(uow, AuditType.Delete, "Delete Content by version performed by user", userId, Constants.System.Root); + scope.Events.Dispatch(DeletedVersions, this, new DeleteRevisionsEventArgs(id, false,/* specificVersion:*/ versionId)); + Audit(AuditType.Delete, "Delete Content by version performed by user", userId, Constants.System.Root); - uow.Complete(); + scope.Complete(); } } @@ -1433,17 +1392,16 @@ namespace Umbraco.Core.Services var evtMsgs = EventMessagesFactory.Get(); var moves = new List>(); - using (var uow = UowProvider.CreateUnitOfWork()) + using (var scope = ScopeProvider.CreateScope()) { - uow.WriteLock(Constants.Locks.ContentTree); - var repository = uow.CreateRepository(); + scope.WriteLock(Constants.Locks.ContentTree); var originalPath = content.Path; var moveEventInfo = new MoveEventInfo(content, originalPath, Constants.System.RecycleBinContent); var moveEventArgs = new MoveEventArgs(evtMsgs, moveEventInfo); - if (uow.Events.DispatchCancelable(Trashing, this, moveEventArgs)) + if (scope.Events.DispatchCancelable(Trashing, this, moveEventArgs)) { - uow.Complete(); + scope.Complete(); return OperationResult.Cancel(evtMsgs); // causes rollback } @@ -1453,8 +1411,8 @@ namespace Umbraco.Core.Services //if (content.HasPublishedVersion) //{ } - PerformMoveLocked(repository, content, Constants.System.RecycleBinContent, null, userId, moves, true); - uow.Events.Dispatch(TreeChanged, this, new TreeChange(content, TreeChangeTypes.RefreshBranch).ToEventArgs()); + PerformMoveLocked(content, Constants.System.RecycleBinContent, null, userId, moves, true); + scope.Events.Dispatch(TreeChanged, this, new TreeChange(content, TreeChangeTypes.RefreshBranch).ToEventArgs()); var moveInfo = moves .Select(x => new MoveEventInfo(x.Item1, x.Item2, x.Item1.ParentId)) @@ -1462,10 +1420,10 @@ namespace Umbraco.Core.Services moveEventArgs.CanCancel = false; moveEventArgs.MoveInfoCollection = moveInfo; - uow.Events.Dispatch(Trashed, this, moveEventArgs); - Audit(uow, AuditType.Move, "Move Content to Recycle Bin performed by user", userId, content.Id); + scope.Events.Dispatch(Trashed, this, moveEventArgs); + Audit(AuditType.Move, "Move Content to Recycle Bin performed by user", userId, content.Id); - uow.Complete(); + scope.Complete(); } return OperationResult.Succeed(evtMsgs); @@ -1493,10 +1451,9 @@ namespace Umbraco.Core.Services var moves = new List>(); - using (var uow = UowProvider.CreateUnitOfWork()) + using (var scope = ScopeProvider.CreateScope()) { - uow.WriteLock(Constants.Locks.ContentTree); - var repository = uow.CreateRepository(); + scope.WriteLock(Constants.Locks.ContentTree); var parent = parentId == Constants.System.Root ? null : GetById(parentId); if (parentId != Constants.System.Root && (parent == null || parent.Trashed)) @@ -1504,9 +1461,9 @@ namespace Umbraco.Core.Services var moveEventInfo = new MoveEventInfo(content, content.Path, parentId); var moveEventArgs = new MoveEventArgs(moveEventInfo); - if (uow.Events.DispatchCancelable(Moving, this, moveEventArgs)) + if (scope.Events.DispatchCancelable(Moving, this, moveEventArgs)) { - uow.Complete(); + scope.Complete(); return; // causes rollback } @@ -1525,9 +1482,9 @@ namespace Umbraco.Core.Services ((Content) content).PublishedState = PublishedState.Unpublishing; } - PerformMoveLocked(repository, content, parentId, parent, userId, moves, trashed); + PerformMoveLocked(content, parentId, parent, userId, moves, trashed); - uow.Events.Dispatch(TreeChanged, this, new TreeChange(content, TreeChangeTypes.RefreshBranch).ToEventArgs()); + scope.Events.Dispatch(TreeChanged, this, new TreeChange(content, TreeChangeTypes.RefreshBranch).ToEventArgs()); var moveInfo = moves //changes .Select(x => new MoveEventInfo(x.Item1, x.Item2, x.Item1.ParentId)) @@ -1535,17 +1492,16 @@ namespace Umbraco.Core.Services moveEventArgs.MoveInfoCollection = moveInfo; moveEventArgs.CanCancel = false; - uow.Events.Dispatch(Moved, this, moveEventArgs); - Audit(uow, AuditType.Move, "Move Content performed by user", userId, content.Id); + scope.Events.Dispatch(Moved, this, moveEventArgs); + Audit(AuditType.Move, "Move Content performed by user", userId, content.Id); - uow.Complete(); + scope.Complete(); } } // MUST be called from within WriteLock // trash indicates whether we are trashing, un-trashing, or not changing anything - private void PerformMoveLocked(IDocumentRepository repository, - IContent content, int parentId, IContent parent, int userId, + private void PerformMoveLocked(IContent content, int parentId, IContent parent, int userId, ICollection> moves, bool? trash) { @@ -1568,7 +1524,7 @@ namespace Umbraco.Core.Services //content.Path = (parent == null ? "-1" : parent.Path) + "," + content.Id; //content.SortOrder = ((ContentRepository) repository).NextChildSortOrder(parentId); //content.Level += levelDelta; - PerformMoveContentLocked(repository, content, userId, trash); + PerformMoveContentLocked(content, userId, trash); // if uow is not immediate, content.Path will be updated only when the UOW commits, // and because we want it now, we have to calculate it by ourselves @@ -1585,15 +1541,15 @@ namespace Umbraco.Core.Services descendant.Path = paths[descendant.Id] = paths[descendant.ParentId] + "," + descendant.Id; Console.WriteLine("path " + descendant.Id + " = " + paths[descendant.Id]); descendant.Level += levelDelta; - PerformMoveContentLocked(repository, descendant, userId, trash); + PerformMoveContentLocked(descendant, userId, trash); } } - private static void PerformMoveContentLocked(IDocumentRepository repository, IContent content, int userId, bool? trash) + private void PerformMoveContentLocked(IContent content, int userId, bool? trash) { if (trash.HasValue) ((ContentBase) content).Trashed = trash.Value; content.WriterId = userId; - repository.Save(content); + _documentRepository.Save(content); } /// @@ -1605,10 +1561,9 @@ namespace Umbraco.Core.Services var deleted = new List(); var evtMsgs = EventMessagesFactory.Get(); // todo - and then? - using (var uow = UowProvider.CreateUnitOfWork()) + using (var scope = ScopeProvider.CreateScope()) { - uow.WriteLock(Constants.Locks.ContentTree); - var repository = uow.CreateRepository(); + scope.WriteLock(Constants.Locks.ContentTree); // v7 EmptyingRecycleBin and EmptiedRecycleBin events are greatly simplified since // each deleted items will have its own deleting/deleted events. so, files and such @@ -1616,28 +1571,28 @@ namespace Umbraco.Core.Services // no idea what those events are for, keep a simplified version var recycleBinEventArgs = new RecycleBinEventArgs(nodeObjectType); - if (uow.Events.DispatchCancelable(EmptyingRecycleBin, this, recycleBinEventArgs)) + if (scope.Events.DispatchCancelable(EmptyingRecycleBin, this, recycleBinEventArgs)) { - uow.Complete(); + scope.Complete(); return; // causes rollback } // emptying the recycle bin means deleting whetever is in there - do it properly! var query = Query().Where(x => x.ParentId == Constants.System.RecycleBinContent); - var contents = repository.Get(query).ToArray(); + var contents = _documentRepository.Get(query).ToArray(); foreach (var content in contents) { - DeleteLocked(uow, repository, content); + DeleteLocked(scope, content); deleted.Add(content); } recycleBinEventArgs.CanCancel = false; recycleBinEventArgs.RecycleBinEmptiedSuccessfully = true; // oh my?! - uow.Events.Dispatch(EmptiedRecycleBin, this, recycleBinEventArgs); - uow.Events.Dispatch(TreeChanged, this, deleted.Select(x => new TreeChange(x, TreeChangeTypes.Remove)).ToEventArgs()); - Audit(uow, AuditType.Delete, "Empty Content Recycle Bin performed by user", 0, Constants.System.RecycleBinContent); + scope.Events.Dispatch(EmptiedRecycleBin, this, recycleBinEventArgs); + scope.Events.Dispatch(TreeChanged, this, deleted.Select(x => new TreeChange(x, TreeChangeTypes.Remove)).ToEventArgs()); + Audit(AuditType.Delete, "Empty Content Recycle Bin performed by user", 0, Constants.System.RecycleBinContent); - uow.Complete(); + scope.Complete(); } } @@ -1674,12 +1629,12 @@ namespace Umbraco.Core.Services var copy = content.DeepCloneWithResetIdentities(); copy.ParentId = parentId; - using (var uow = UowProvider.CreateUnitOfWork()) + using (var scope = ScopeProvider.CreateScope()) { var copyEventArgs = new CopyEventArgs(content, copy, true, parentId, relateToOriginal); - if (uow.Events.DispatchCancelable(Copying, this, copyEventArgs)) + if (scope.Events.DispatchCancelable(Copying, this, copyEventArgs)) { - uow.Complete(); + scope.Complete(); return null; } @@ -1689,8 +1644,7 @@ namespace Umbraco.Core.Services var copies = new List>(); - uow.WriteLock(Constants.Locks.ContentTree); - var repository = uow.CreateRepository(); + scope.WriteLock(Constants.Locks.ContentTree); // a copy is not published (but not really unpublishing either) // update the create author and last edit author @@ -1704,17 +1658,15 @@ namespace Umbraco.Core.Services currentPermissions.RemoveWhere(p => p.IsDefaultPermissions); // save and flush because we need the ID for the recursive Copying events - repository.Save(copy); + _documentRepository.Save(copy); //add permissions if (currentPermissions.Count > 0) { var permissionSet = new ContentPermissionSet(copy, currentPermissions); - repository.AddOrUpdatePermissions(permissionSet); + _documentRepository.AddOrUpdatePermissions(permissionSet); } - uow.Flush(); - // keep track of copies copies.Add(Tuple.Create(content, copy)); var idmap = new Dictionary { [content.Id] = copy.Id }; @@ -1729,7 +1681,7 @@ namespace Umbraco.Core.Services var descendantCopy = descendant.DeepCloneWithResetIdentities(); descendantCopy.ParentId = parentId; - if (uow.Events.DispatchCancelable(Copying, this, new CopyEventArgs(descendant, descendantCopy, parentId))) + if (scope.Events.DispatchCancelable(Copying, this, new CopyEventArgs(descendant, descendantCopy, parentId))) continue; // a copy is not published (but not really unpublishing either) @@ -1740,8 +1692,7 @@ namespace Umbraco.Core.Services descendantCopy.WriterId = userId; // save and flush (see above) - repository.Save(descendantCopy); - uow.Flush(); + _documentRepository.Save(descendantCopy); copies.Add(Tuple.Create(descendant, descendantCopy)); idmap[descendant.Id] = descendantCopy.Id; @@ -1752,12 +1703,12 @@ namespace Umbraco.Core.Services // - tags should be handled by the content repository // - a copy is unpublished and therefore has no impact on tags in DB - uow.Events.Dispatch(TreeChanged, this, new TreeChange(copy, TreeChangeTypes.RefreshBranch).ToEventArgs()); + scope.Events.Dispatch(TreeChanged, this, new TreeChange(copy, TreeChangeTypes.RefreshBranch).ToEventArgs()); foreach (var x in copies) - uow.Events.Dispatch(Copied, this, new CopyEventArgs(x.Item1, x.Item2, false, x.Item2.ParentId, relateToOriginal)); - Audit(uow, AuditType.Copy, "Copy Content performed by user", content.WriterId, content.Id); + scope.Events.Dispatch(Copied, this, new CopyEventArgs(x.Item1, x.Item2, false, x.Item2.ParentId, relateToOriginal)); + Audit(AuditType.Copy, "Copy Content performed by user", content.WriterId, content.Id); - uow.Complete(); + scope.Complete(); } return copy; @@ -1771,12 +1722,12 @@ namespace Umbraco.Core.Services /// True if sending publication was succesfull otherwise false public bool SendToPublication(IContent content, int userId = 0) { - using (var uow = UowProvider.CreateUnitOfWork()) + using (var scope = ScopeProvider.CreateScope()) { var sendToPublishEventArgs = new SendToPublishEventArgs(content); - if (uow.Events.DispatchCancelable(SendingToPublish, this, sendToPublishEventArgs)) + if (scope.Events.DispatchCancelable(SendingToPublish, this, sendToPublishEventArgs)) { - uow.Complete(); + scope.Complete(); return false; } @@ -1785,8 +1736,8 @@ namespace Umbraco.Core.Services Save(content, userId); sendToPublishEventArgs.CanCancel = false; - uow.Events.Dispatch(SentToPublish, this, sendToPublishEventArgs); - Audit(uow, AuditType.SendToPublish, "Send to Publish performed by user", content.WriterId, content.Id); + scope.Events.Dispatch(SentToPublish, this, sendToPublishEventArgs); + Audit(AuditType.SendToPublish, "Send to Publish performed by user", content.WriterId, content.Id); } return true; @@ -1809,17 +1760,16 @@ namespace Umbraco.Core.Services var itemsA = items.ToArray(); if (itemsA.Length == 0) return true; - using (var uow = UowProvider.CreateUnitOfWork()) + using (var scope = ScopeProvider.CreateScope()) { var saveEventArgs = new SaveEventArgs(itemsA); - if (raiseEvents && uow.Events.DispatchCancelable(Saving, this, saveEventArgs, "Saving")) + if (raiseEvents && scope.Events.DispatchCancelable(Saving, this, saveEventArgs, "Saving")) return false; var published = new List(); var saved = new List(); - uow.WriteLock(Constants.Locks.ContentTree); - var repository = uow.CreateRepository(); + scope.WriteLock(Constants.Locks.ContentTree); var sortOrder = 0; foreach (var content in itemsA) @@ -1843,23 +1793,23 @@ namespace Umbraco.Core.Services // save saved.Add(content); - repository.Save(content); + _documentRepository.Save(content); } if (raiseEvents) { saveEventArgs.CanCancel = false; - uow.Events.Dispatch(Saved, this, saveEventArgs, "Saved"); + scope.Events.Dispatch(Saved, this, saveEventArgs, "Saved"); } - uow.Events.Dispatch(TreeChanged, this, saved.Select(x => new TreeChange(x, TreeChangeTypes.RefreshNode)).ToEventArgs()); + scope.Events.Dispatch(TreeChanged, this, saved.Select(x => new TreeChange(x, TreeChangeTypes.RefreshNode)).ToEventArgs()); if (raiseEvents && published.Any()) - uow.Events.Dispatch(Published, this, new PublishEventArgs(published, false, false), "Published"); + scope.Events.Dispatch(Published, this, new PublishEventArgs(published, false, false), "Published"); - Audit(uow, AuditType.Sort, "Sorting content performed by user", userId, 0); + Audit(AuditType.Sort, "Sorting content performed by user", userId, 0); - uow.Complete(); + scope.Complete(); } return true; @@ -1876,19 +1826,18 @@ namespace Umbraco.Core.Services /// An Enumerable list of objects internal IEnumerable GetPublishedDescendants(IContent content) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - uow.ReadLock(Constants.Locks.ContentTree); - var repository = uow.CreateRepository(); - return GetPublishedDescendantsLocked(uow, repository, content).ToArray(); // ToArray important in uow! + scope.ReadLock(Constants.Locks.ContentTree); + return GetPublishedDescendantsLocked(content).ToArray(); // ToArray important in uow! } } - internal IEnumerable GetPublishedDescendantsLocked(IScopeUnitOfWork uow, IDocumentRepository repository, IContent content) + internal IEnumerable GetPublishedDescendantsLocked(IContent content) { var pathMatch = content.Path + ","; var query = Query().Where(x => x.Id != content.Id && x.Path.StartsWith(pathMatch) /*&& x.Trashed == false*/); - var contents = repository.Get(query); + var contents = _documentRepository.Get(query); // beware! contents contains all published version below content // including those that are not directly published because below an unpublished content @@ -1909,10 +1858,9 @@ namespace Umbraco.Core.Services #region Private Methods - private void Audit(IUnitOfWork uow, AuditType type, string message, int userId, int objectId) + private void Audit(AuditType type, string message, int userId, int objectId) { - var repo = uow.CreateRepository(); - repo.Save(new AuditItem(objectId, message, type, userId)); + _auditRepository.Save(new AuditItem(objectId, message, type, userId)); } #endregion @@ -2064,10 +2012,10 @@ namespace Umbraco.Core.Services #region Publishing Strategies // ensures that a document can be published - internal PublishResult StrategyCanPublish(IScopeUnitOfWork uow, IContent content, int userId, bool checkPath, EventMessages evtMsgs) + internal PublishResult StrategyCanPublish(IScope scope, IContent content, int userId, bool checkPath, EventMessages evtMsgs) { // raise Publishing event - if (uow.Events.DispatchCancelable(Publishing, this, new PublishEventArgs(content, evtMsgs))) + if (scope.Events.DispatchCancelable(Publishing, this, new PublishEventArgs(content, evtMsgs))) { Logger.Info($"Document \"'{content.Name}\" (id={content.Id}) cannot be published: publishing was cancelled."); return new PublishResult(PublishResultType.FailedCancelledByEvent, evtMsgs, content); @@ -2113,7 +2061,7 @@ namespace Umbraco.Core.Services } // publishes a document - internal PublishResult StrategyPublish(IScopeUnitOfWork uow, IContent content, bool canPublish, int userId, EventMessages evtMsgs) + internal PublishResult StrategyPublish(IScope scope, IContent content, bool canPublish, int userId, EventMessages evtMsgs) { // note: when used at top-level, StrategyCanPublish with checkPath=true should have run already // and alreadyCheckedCanPublish should be true, so not checking again. when used at nested level, @@ -2121,7 +2069,7 @@ namespace Umbraco.Core.Services var result = canPublish ? new PublishResult(evtMsgs, content) // already know we can - : StrategyCanPublish(uow, content, userId, /*checkPath:*/ false, evtMsgs); // else check + : StrategyCanPublish(scope, content, userId, /*checkPath:*/ false, evtMsgs); // else check if (result.Success == false) return result; @@ -2134,10 +2082,10 @@ namespace Umbraco.Core.Services } // ensures that a document can be unpublished - internal PublishResult StrategyCanUnpublish(IScopeUnitOfWork uow, IContent content, int userId, EventMessages evtMsgs) + internal PublishResult StrategyCanUnpublish(IScope scope, IContent content, int userId, EventMessages evtMsgs) { // raise UnPublishing event - if (uow.Events.DispatchCancelable(UnPublishing, this, new PublishEventArgs(content, evtMsgs))) + if (scope.Events.DispatchCancelable(UnPublishing, this, new PublishEventArgs(content, evtMsgs))) { Logger.Info($"Document \"{content.Name}\" (id={content.Id}) cannot be unpublished: unpublishing was cancelled."); return new PublishResult(PublishResultType.FailedCancelledByEvent, evtMsgs, content); @@ -2147,11 +2095,11 @@ namespace Umbraco.Core.Services } // unpublishes a document - internal PublishResult StrategyUnpublish(IScopeUnitOfWork uow, IContent content, bool canUnpublish, int userId, EventMessages evtMsgs) + internal PublishResult StrategyUnpublish(IScope scope, IContent content, bool canUnpublish, int userId, EventMessages evtMsgs) { var attempt = canUnpublish ? new PublishResult(evtMsgs, content) // already know we can - : StrategyCanUnpublish(uow, content, userId, evtMsgs); // else check + : StrategyCanUnpublish(scope, content, userId, evtMsgs); // else check if (attempt.Success == false) return attempt; @@ -2203,17 +2151,16 @@ namespace Umbraco.Core.Services // PerformMoveLocked and DeleteLocked that must be applied immediately, // no point queuing operations // - using (var uow = UowProvider.CreateUnitOfWork(immediate: true)) + using (var scope = ScopeProvider.CreateScope()) { - uow.WriteLock(Constants.Locks.ContentTree); - var repository = uow.CreateRepository(); + scope.WriteLock(Constants.Locks.ContentTree); var query = Query().WhereIn(x => x.ContentTypeId, contentTypeIdsA); - var contents = repository.Get(query).ToArray(); + var contents = _documentRepository.Get(query).ToArray(); - if (uow.Events.DispatchCancelable(Deleting, this, new DeleteEventArgs(contents))) + if (scope.Events.DispatchCancelable(Deleting, this, new DeleteEventArgs(contents))) { - uow.Complete(); + scope.Complete(); return; } @@ -2225,22 +2172,22 @@ namespace Umbraco.Core.Services // but... UnPublishing event makes no sense (not going to cancel?) and no need to save // just raise the event if (content.Trashed == false && content.Published) - uow.Events.Dispatch(UnPublished, this, new PublishEventArgs(content, false, false), "UnPublished"); + scope.Events.Dispatch(UnPublished, this, new PublishEventArgs(content, false, false), "UnPublished"); // if current content has children, move them to trash var c = content; var childQuery = Query().Where(x => x.ParentId == c.Id); - var children = repository.Get(childQuery); + var children = _documentRepository.Get(childQuery); foreach (var child in children) { // see MoveToRecycleBin - PerformMoveLocked(repository, child, Constants.System.RecycleBinContent, null, userId, moves, true); + PerformMoveLocked(child, Constants.System.RecycleBinContent, null, userId, moves, true); changes.Add(new TreeChange(content, TreeChangeTypes.RefreshBranch)); } // delete content // triggers the deleted event (and handles the files) - DeleteLocked(uow, repository, content); + DeleteLocked(scope, content); changes.Add(new TreeChange(content, TreeChangeTypes.Remove)); } @@ -2248,12 +2195,12 @@ namespace Umbraco.Core.Services .Select(x => new MoveEventInfo(x.Item1, x.Item2, x.Item1.ParentId)) .ToArray(); if (moveInfos.Length > 0) - uow.Events.Dispatch(Trashed, this, new MoveEventArgs(false, moveInfos), "Trashed"); - uow.Events.Dispatch(TreeChanged, this, changes.ToEventArgs()); + scope.Events.Dispatch(Trashed, this, new MoveEventArgs(false, moveInfos), "Trashed"); + scope.Events.Dispatch(TreeChanged, this, changes.ToEventArgs()); - Audit(uow, AuditType.Delete, $"Delete Content of Type {string.Join(",", contentTypeIdsA)} performed by user", userId, Constants.System.Root); + Audit(AuditType.Delete, $"Delete Content of Type {string.Join(",", contentTypeIdsA)} performed by user", userId, Constants.System.Root); - uow.Complete(); + scope.Complete(); } } @@ -2268,15 +2215,14 @@ namespace Umbraco.Core.Services DeleteOfTypes(new[] { contentTypeId }, userId); } - private IContentType GetContentType(IScopeUnitOfWork uow, string contentTypeAlias) + private IContentType GetContentType(IScope scope, string contentTypeAlias) { if (string.IsNullOrWhiteSpace(contentTypeAlias)) throw new ArgumentNullOrEmptyException(nameof(contentTypeAlias)); - uow.ReadLock(Constants.Locks.ContentTypes); + scope.ReadLock(Constants.Locks.ContentTypes); - var repository = uow.CreateRepository(); var query = Query().Where(x => x.Alias == contentTypeAlias); - var contentType = repository.Get(query).FirstOrDefault(); + var contentType = _contentTypeRepository.Get(query).FirstOrDefault(); if (contentType == null) throw new Exception($"No ContentType matching the passed in Alias: '{contentTypeAlias}' was found"); // causes rollback @@ -2288,9 +2234,9 @@ namespace Umbraco.Core.Services { if (string.IsNullOrWhiteSpace(contentTypeAlias)) throw new ArgumentNullOrEmptyException(nameof(contentTypeAlias)); - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - return GetContentType(uow, contentTypeAlias); + return GetContentType(scope, contentTypeAlias); } } @@ -2300,11 +2246,10 @@ namespace Umbraco.Core.Services public IContent GetBlueprintById(int id) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - uow.ReadLock(Constants.Locks.ContentTree); - var repository = uow.CreateRepository(); - var blueprint = repository.Get(id); + scope.ReadLock(Constants.Locks.ContentTree); + var blueprint = _documentBlueprintRepository.Get(id); if (blueprint != null) ((Content) blueprint).Blueprint = true; return blueprint; @@ -2313,11 +2258,10 @@ namespace Umbraco.Core.Services public IContent GetBlueprintById(Guid id) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - uow.ReadLock(Constants.Locks.ContentTree); - var repository = uow.CreateRepository(); - var blueprint = repository.Get(id); + scope.ReadLock(Constants.Locks.ContentTree); + var blueprint = _documentBlueprintRepository.Get(id); if (blueprint != null) ((Content) blueprint).Blueprint = true; return blueprint; @@ -2332,40 +2276,37 @@ namespace Umbraco.Core.Services ((Content) content).Blueprint = true; - using (var uow = UowProvider.CreateUnitOfWork()) + using (var scope = ScopeProvider.CreateScope()) { - uow.WriteLock(Constants.Locks.ContentTree); + scope.WriteLock(Constants.Locks.ContentTree); if (string.IsNullOrWhiteSpace(content.Name)) { throw new ArgumentException("Cannot save content blueprint with empty name."); } - var repository = uow.CreateRepository(); - if (content.HasIdentity == false) { content.CreatorId = userId; } content.WriterId = userId; - repository.Save(content); + _documentBlueprintRepository.Save(content); - uow.Events.Dispatch(SavedBlueprint, this, new SaveEventArgs(content), "SavedBlueprint"); + scope.Events.Dispatch(SavedBlueprint, this, new SaveEventArgs(content), "SavedBlueprint"); - uow.Complete(); + scope.Complete(); } } public void DeleteBlueprint(IContent content, int userId = 0) { - using (var uow = UowProvider.CreateUnitOfWork()) + using (var scope = ScopeProvider.CreateScope()) { - uow.WriteLock(Constants.Locks.ContentTree); - var repository = uow.CreateRepository(); - repository.Delete(content); - uow.Events.Dispatch(DeletedBlueprint, this, new DeleteEventArgs(content), "DeletedBlueprint"); - uow.Complete(); + scope.WriteLock(Constants.Locks.ContentTree); + _documentBlueprintRepository.Delete(content); + scope.Events.Dispatch(DeletedBlueprint, this, new DeleteEventArgs(content), "DeletedBlueprint"); + scope.Complete(); } } @@ -2388,16 +2329,14 @@ namespace Umbraco.Core.Services public IEnumerable GetBlueprintsForContentTypes(params int[] contentTypeId) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - var repository = uow.CreateRepository(); - var query = Query(); if (contentTypeId.Length > 0) { query.Where(x => contentTypeId.Contains(x.ContentTypeId)); } - return repository.Get(query).Select(x => + return _documentBlueprintRepository.Get(query).Select(x => { ((Content) x).Blueprint = true; return x; diff --git a/src/Umbraco.Core/Services/ContentTypeService.cs b/src/Umbraco.Core/Services/ContentTypeService.cs index 24bf580fd6..85e1efd29b 100644 --- a/src/Umbraco.Core/Services/ContentTypeService.cs +++ b/src/Umbraco.Core/Services/ContentTypeService.cs @@ -4,7 +4,7 @@ using Umbraco.Core.Events; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Persistence.Repositories; -using Umbraco.Core.Persistence.UnitOfWork; +using Umbraco.Core.Scoping; namespace Umbraco.Core.Services { @@ -13,13 +13,15 @@ namespace Umbraco.Core.Services /// internal class ContentTypeService : ContentTypeServiceBase, IContentTypeService { - public ContentTypeService(IScopeUnitOfWorkProvider provider, ILogger logger, IEventMessagesFactory eventMessagesFactory, IContentService contentService) - : base(provider, logger, eventMessagesFactory) + public ContentTypeService(IScopeProvider provider, ILogger logger, IEventMessagesFactory eventMessagesFactory, IContentService contentService, + IContentTypeRepository repository, IAuditRepository auditRepository, IEntityContainerRepository entityContainerRepository, IEntityRepository entityRepository) + : base(provider, logger, eventMessagesFactory, repository, auditRepository, entityContainerRepository, entityRepository) { ContentService = contentService; } protected override IContentTypeService This => this; + // beware! order is important to avoid deadlocks protected override int[] ReadLockIds { get; } = { Constants.Locks.ContentTypes }; protected override int[] WriteLockIds { get; } = { Constants.Locks.ContentTree, Constants.Locks.ContentTypes }; @@ -41,12 +43,11 @@ namespace Umbraco.Core.Services /// Beware! Works accross content, media and member types. public IEnumerable GetAllPropertyTypeAliases() { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { // that one is special because it works accross content, media and member types - uow.ReadLock(Constants.Locks.ContentTypes, Constants.Locks.MediaTypes, Constants.Locks.MemberTypes); - var repo = uow.CreateRepository(); - return repo.GetAllPropertyTypeAliases(); + scope.ReadLock(Constants.Locks.ContentTypes, Constants.Locks.MediaTypes, Constants.Locks.MemberTypes); + return Repository.GetAllPropertyTypeAliases(); } } @@ -58,12 +59,11 @@ namespace Umbraco.Core.Services /// Beware! Works accross content, media and member types. public IEnumerable GetAllContentTypeAliases(params Guid[] guids) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { // that one is special because it works accross content, media and member types - uow.ReadLock(Constants.Locks.ContentTypes, Constants.Locks.MediaTypes, Constants.Locks.MemberTypes); - var repo = uow.CreateRepository(); - return repo.GetAllContentTypeAliases(guids); + scope.ReadLock(Constants.Locks.ContentTypes, Constants.Locks.MediaTypes, Constants.Locks.MemberTypes); + return Repository.GetAllContentTypeAliases(guids); } } @@ -75,12 +75,11 @@ namespace Umbraco.Core.Services /// Beware! Works accross content, media and member types. public IEnumerable GetAllContentTypeIds(string[] aliases) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { // that one is special because it works accross content, media and member types - uow.ReadLock(Constants.Locks.ContentTypes, Constants.Locks.MediaTypes, Constants.Locks.MemberTypes); - var repo = uow.CreateRepository(); - return repo.GetAllContentTypeIds(aliases); + scope.ReadLock(Constants.Locks.ContentTypes, Constants.Locks.MediaTypes, Constants.Locks.MemberTypes); + return Repository.GetAllContentTypeIds(aliases); } } diff --git a/src/Umbraco.Core/Services/ContentTypeServiceBase.cs b/src/Umbraco.Core/Services/ContentTypeServiceBase.cs index 8902c0864b..56a3325880 100644 --- a/src/Umbraco.Core/Services/ContentTypeServiceBase.cs +++ b/src/Umbraco.Core/Services/ContentTypeServiceBase.cs @@ -1,12 +1,12 @@ using Umbraco.Core.Events; using Umbraco.Core.Logging; -using Umbraco.Core.Persistence.UnitOfWork; +using Umbraco.Core.Scoping; namespace Umbraco.Core.Services { internal abstract class ContentTypeServiceBase : ScopeRepositoryService { - protected ContentTypeServiceBase(IScopeUnitOfWorkProvider provider, ILogger logger, IEventMessagesFactory eventMessagesFactory) + protected ContentTypeServiceBase(IScopeProvider provider, ILogger logger, IEventMessagesFactory eventMessagesFactory) : base(provider, logger, eventMessagesFactory) { } } diff --git a/src/Umbraco.Core/Services/ContentTypeServiceBaseOfTItemTService.cs b/src/Umbraco.Core/Services/ContentTypeServiceBaseOfTItemTService.cs index 9ba883a441..c43e5fdcca 100644 --- a/src/Umbraco.Core/Services/ContentTypeServiceBaseOfTItemTService.cs +++ b/src/Umbraco.Core/Services/ContentTypeServiceBaseOfTItemTService.cs @@ -1,8 +1,8 @@ -using System.Runtime.CompilerServices; -using Umbraco.Core.Events; +using Umbraco.Core.Events; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Persistence.UnitOfWork; +using Umbraco.Core.Scoping; using Umbraco.Core.Services.Changes; namespace Umbraco.Core.Services @@ -11,7 +11,7 @@ namespace Umbraco.Core.Services where TItem : class, IContentTypeComposition where TService : class, IContentTypeServiceBase { - protected ContentTypeServiceBase(IScopeUnitOfWorkProvider provider, ILogger logger, IEventMessagesFactory eventMessagesFactory) + protected ContentTypeServiceBase(IScopeProvider provider, ILogger logger, IEventMessagesFactory eventMessagesFactory) : base(provider, logger, eventMessagesFactory) { } @@ -37,9 +37,9 @@ namespace Umbraco.Core.Services // fixme - can we have issues with event names? - protected void OnChanged(IScopeUnitOfWork uow, ContentTypeChange.EventArgs args) + protected void OnChanged(IScope scope, ContentTypeChange.EventArgs args) { - uow.Events.Dispatch(Changed, This, args, "Changed"); + scope.Events.Dispatch(Changed, This, args, "Changed"); } protected void OnUowRefreshedEntity(ContentTypeChange.EventArgs args) @@ -49,89 +49,89 @@ namespace Umbraco.Core.Services } // fixme what is thsi? - protected void OnSaving(IScopeUnitOfWork uow, SaveEventArgs args) + protected void OnSaving(IScope scope, SaveEventArgs args) { Saving.RaiseEvent(args, This); } - protected bool OnSavingCancelled(IScopeUnitOfWork uow, SaveEventArgs args) + protected bool OnSavingCancelled(IScope scope, SaveEventArgs args) { - return uow.Events.DispatchCancelable(Saving, This, args); + return scope.Events.DispatchCancelable(Saving, This, args); } - protected void OnSaved(IScopeUnitOfWork uow, SaveEventArgs args) + protected void OnSaved(IScope scope, SaveEventArgs args) { - uow.Events.Dispatch(Saved, This, args); + scope.Events.Dispatch(Saved, This, args); } // fixme what is thsi? - protected void OnDeleting(IScopeUnitOfWork uow, DeleteEventArgs args) + protected void OnDeleting(IScope scope, DeleteEventArgs args) { Deleting.RaiseEvent(args, This); } - protected bool OnDeletingCancelled(IScopeUnitOfWork uow, DeleteEventArgs args) + protected bool OnDeletingCancelled(IScope scope, DeleteEventArgs args) { - return uow.Events.DispatchCancelable(Deleting, This, args); + return scope.Events.DispatchCancelable(Deleting, This, args); } - protected void OnDeleted(IScopeUnitOfWork uow, DeleteEventArgs args) + protected void OnDeleted(IScope scope, DeleteEventArgs args) { - uow.Events.Dispatch(Deleted, This, args); + scope.Events.Dispatch(Deleted, This, args); } // fixme what is thsi? - protected void OnMoving(IScopeUnitOfWork uow, MoveEventArgs args) + protected void OnMoving(IScope scope, MoveEventArgs args) { Moving.RaiseEvent(args, This); } - protected bool OnMovingCancelled(IScopeUnitOfWork uow, MoveEventArgs args) + protected bool OnMovingCancelled(IScope scope, MoveEventArgs args) { - return uow.Events.DispatchCancelable(Moving, This, args); + return scope.Events.DispatchCancelable(Moving, This, args); } - protected void OnMoved(IScopeUnitOfWork uow, MoveEventArgs args) + protected void OnMoved(IScope scope, MoveEventArgs args) { - uow.Events.Dispatch(Moved, This, args); + scope.Events.Dispatch(Moved, This, args); } // fixme what is this? - protected void OnSavingContainer(IScopeUnitOfWork uow, SaveEventArgs args) + protected void OnSavingContainer(IScope scope, SaveEventArgs args) { SavingContainer.RaiseEvent(args, This); } - protected bool OnSavingContainerCancelled(IScopeUnitOfWork uow, SaveEventArgs args) + protected bool OnSavingContainerCancelled(IScope scope, SaveEventArgs args) { - return uow.Events.DispatchCancelable(SavingContainer, This, args); + return scope.Events.DispatchCancelable(SavingContainer, This, args); } - protected void OnSavedContainer(IScopeUnitOfWork uow, SaveEventArgs args) + protected void OnSavedContainer(IScope scope, SaveEventArgs args) { - uow.Events.DispatchCancelable(SavedContainer, This, args); + scope.Events.DispatchCancelable(SavedContainer, This, args); } - protected void OnRenamedContainer(IScopeUnitOfWork uow, SaveEventArgs args) + protected void OnRenamedContainer(IScope scope, SaveEventArgs args) { // fixme changing the name of the event?! - uow.Events.DispatchCancelable(SavedContainer, This, args, "RenamedContainer"); + scope.Events.DispatchCancelable(SavedContainer, This, args, "RenamedContainer"); } // fixme what is this? - protected void OnDeletingContainer(IScopeUnitOfWork uow, DeleteEventArgs args) + protected void OnDeletingContainer(IScope scope, DeleteEventArgs args) { DeletingContainer.RaiseEvent(args, This); } - protected bool OnDeletingContainerCancelled(IScopeUnitOfWork uow, DeleteEventArgs args) + protected bool OnDeletingContainerCancelled(IScope scope, DeleteEventArgs args) { - return uow.Events.DispatchCancelable(DeletingContainer, This, args); + return scope.Events.DispatchCancelable(DeletingContainer, This, args); } - protected void OnDeletedContainer(IScopeUnitOfWork uow, DeleteEventArgs args) + protected void OnDeletedContainer(IScope scope, DeleteEventArgs args) { - uow.Events.Dispatch(DeletedContainer, This, args); + scope.Events.Dispatch(DeletedContainer, This, args); } } } diff --git a/src/Umbraco.Core/Services/ContentTypeServiceBaseOfTRepositoryTItemTService.cs b/src/Umbraco.Core/Services/ContentTypeServiceBaseOfTRepositoryTItemTService.cs index a01bf49a1c..a36f83b4e3 100644 --- a/src/Umbraco.Core/Services/ContentTypeServiceBaseOfTRepositoryTItemTService.cs +++ b/src/Umbraco.Core/Services/ContentTypeServiceBaseOfTRepositoryTItemTService.cs @@ -6,10 +6,9 @@ using Umbraco.Core.Exceptions; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.EntityBase; -using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.Repositories.Implement; -using Umbraco.Core.Persistence.UnitOfWork; +using Umbraco.Core.Scoping; using Umbraco.Core.Services.Changes; namespace Umbraco.Core.Services @@ -19,10 +18,21 @@ namespace Umbraco.Core.Services where TItem : class, IContentTypeComposition where TService : class, IContentTypeServiceBase { - protected ContentTypeServiceBase(IScopeUnitOfWorkProvider provider, ILogger logger, IEventMessagesFactory eventMessagesFactory) - : base(provider, logger, eventMessagesFactory) - { } + private readonly IAuditRepository _auditRepository; + private readonly IEntityContainerRepository _containerRepository; + private readonly IEntityRepository _entityRepository; + protected ContentTypeServiceBase(IScopeProvider provider, ILogger logger, IEventMessagesFactory eventMessagesFactory, + TRepository repository, IAuditRepository auditRepository, IEntityContainerRepository containerRepository, IEntityRepository entityRepository) + : base(provider, logger, eventMessagesFactory) + { + Repository = repository; + _auditRepository = auditRepository; + _containerRepository = containerRepository; + _entityRepository = entityRepository; + } + + protected TRepository Repository { get; } protected abstract int[] WriteLockIds { get; } protected abstract int[] ReadLockIds { get; } @@ -32,11 +42,10 @@ namespace Umbraco.Core.Services { try { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - var repo = uow.CreateRepository(); - uow.ReadLock(ReadLockIds); - ValidateLocked(repo, compo); + scope.ReadLock(ReadLockIds); + ValidateLocked(compo); } return Attempt.Succeed(); } @@ -46,7 +55,7 @@ namespace Umbraco.Core.Services } } - protected void ValidateLocked(TRepository repository, TItem compositionContentType) + protected void ValidateLocked(TItem compositionContentType) { // performs business-level validation of the composition // should ensure that it is absolutely safe to save the composition @@ -54,7 +63,7 @@ namespace Umbraco.Core.Services // eg maybe a property has been added, with an alias that's OK (no conflict with ancestors) // but that cannot be used (conflict with descendants) - var allContentTypes = repository.GetMany(new int[0]).Cast().ToArray(); + var allContentTypes = Repository.GetMany(new int[0]).Cast().ToArray(); var compositionAliases = compositionContentType.CompositionAliases(); var compositions = allContentTypes.Where(x => compositionAliases.Any(y => x.Alias.Equals(y))); @@ -136,8 +145,8 @@ namespace Umbraco.Core.Services // existing property alias change? var hasAnyPropertyChangedAlias = contentType.PropertyTypes.Any(propertyType => { - var dirtyProperty = propertyType as IRememberBeingDirty; - if (dirtyProperty == null) throw new Exception("oops"); + if (!(propertyType is IRememberBeingDirty dirtyProperty)) + throw new Exception("oops"); // skip new properties var isNewProperty = dirtyProperty.WasPropertyDirty("HasIdentity"); @@ -194,101 +203,91 @@ namespace Umbraco.Core.Services public TItem Get(int id) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - var repo = uow.CreateRepository(); - uow.ReadLock(ReadLockIds); - return repo.Get(id); + scope.ReadLock(ReadLockIds); + return Repository.Get(id); } } public TItem Get(string alias) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - var repo = uow.CreateRepository(); - uow.ReadLock(ReadLockIds); - return repo.Get(alias); + scope.ReadLock(ReadLockIds); + return Repository.Get(alias); } } public TItem Get(Guid id) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - var repo = uow.CreateRepository(); - uow.ReadLock(ReadLockIds); - return repo.Get(id); + scope.ReadLock(ReadLockIds); + return Repository.Get(id); } } public IEnumerable GetAll(params int[] ids) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - var repo = uow.CreateRepository(); - uow.ReadLock(ReadLockIds); - return repo.GetMany(ids); + scope.ReadLock(ReadLockIds); + return Repository.GetMany(ids); } } public IEnumerable GetAll(params Guid[] ids) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - var repo = uow.CreateRepository(); - uow.ReadLock(ReadLockIds); - // IReadRepository is explicitely implemented, need to cast the repo - return ((IReadRepository) repo).GetMany(ids); + scope.ReadLock(ReadLockIds); + return Repository.GetMany(ids); } } public IEnumerable GetChildren(int id) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - var repo = uow.CreateRepository(); - uow.ReadLock(ReadLockIds); + scope.ReadLock(ReadLockIds); var query = Query().Where(x => x.ParentId == id); - return repo.Get(query); + return Repository.Get(query); } } public IEnumerable GetChildren(Guid id) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - var repo = uow.CreateRepository(); - uow.ReadLock(ReadLockIds); + scope.ReadLock(ReadLockIds); var found = Get(id); if (found == null) return Enumerable.Empty(); var query = Query().Where(x => x.ParentId == found.Id); - return repo.Get(query); + return Repository.Get(query); } } public bool HasChildren(int id) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - var repo = uow.CreateRepository(); - uow.ReadLock(ReadLockIds); + scope.ReadLock(ReadLockIds); var query = Query().Where(x => x.ParentId == id); - var count = repo.Count(query); + var count = Repository.Count(query); return count > 0; } } public bool HasChildren(Guid id) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - var repo = uow.CreateRepository(); - uow.ReadLock(ReadLockIds); + scope.ReadLock(ReadLockIds); var found = Get(id); if (found == null) return false; var query = Query().Where(x => x.ParentId == found.Id); - var count = repo.Count(query); + var count = Repository.Count(query); return count > 0; } } @@ -300,23 +299,21 @@ namespace Umbraco.Core.Services /// public bool HasContainerInPath(string contentPath) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { // can use same repo for both content and media - var repo = uow.CreateRepository(); - return repo.HasContainerInPath(contentPath); + return Repository.HasContainerInPath(contentPath); } } public IEnumerable GetDescendants(int id, bool andSelf) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - var repo = uow.CreateRepository(); - uow.ReadLock(ReadLockIds); + scope.ReadLock(ReadLockIds); var descendants = new List(); - if (andSelf) descendants.Add(repo.Get(id)); + if (andSelf) descendants.Add(Repository.Get(id)); var ids = new Stack(); ids.Push(id); @@ -324,7 +321,7 @@ namespace Umbraco.Core.Services { var i = ids.Pop(); var query = Query().Where(x => x.ParentId == i); - var result = repo.Get(query).ToArray(); + var result = Repository.Get(query).ToArray(); foreach (var c in result) { @@ -339,10 +336,9 @@ namespace Umbraco.Core.Services public IEnumerable GetComposedOf(int id) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - var repo = uow.CreateRepository(); - uow.ReadLock(ReadLockIds); + scope.ReadLock(ReadLockIds); // hash set handles duplicates var composed = new HashSet(new DelegateEqualityComparer( @@ -355,7 +351,7 @@ namespace Umbraco.Core.Services while (ids.Count > 0) { var i = ids.Pop(); - var result = repo.GetTypesDirectlyComposedOf(i).ToArray(); + var result = Repository.GetTypesDirectlyComposedOf(i).ToArray(); foreach (var c in result) { @@ -370,11 +366,10 @@ namespace Umbraco.Core.Services public int Count() { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - var repo = uow.CreateRepository(); - uow.ReadLock(ReadLockIds); - return repo.Count(Query()); + scope.ReadLock(ReadLockIds); + return Repository.Count(Query()); } } @@ -384,41 +379,39 @@ namespace Umbraco.Core.Services public void Save(TItem item, int userId = 0) { - using (var uow = UowProvider.CreateUnitOfWork()) + using (var scope = ScopeProvider.CreateScope()) { var saveEventArgs = new SaveEventArgs(item); - if (OnSavingCancelled(uow, saveEventArgs)) + if (OnSavingCancelled(scope, saveEventArgs)) { - uow.Complete(); + scope.Complete(); return; } if (string.IsNullOrWhiteSpace(item.Name)) throw new ArgumentException("Cannot save item with empty name."); - var repo = uow.CreateRepository(); - uow.WriteLock(WriteLockIds); + scope.WriteLock(WriteLockIds); // validate the DAG transform, within the lock - ValidateLocked(repo, item); // throws if invalid + ValidateLocked(item); // throws if invalid item.CreatorId = userId; if (item.Description == string.Empty) item.Description = null; - repo.Save(item); // also updates content/media/member items + Repository.Save(item); // also updates content/media/member items // figure out impacted content types var changes = ComposeContentTypeChanges(item).ToArray(); var args = changes.ToEventArgs(); - uow.Flush(); // to db but no commit yet - for uow event OnUowRefreshedEntity(args); - OnChanged(uow, args); + OnChanged(scope, args); saveEventArgs.CanCancel = false; - OnSaved(uow, saveEventArgs); + OnSaved(scope, saveEventArgs); - Audit(uow, AuditType.Save, $"Save {typeof(TItem).Name} performed by user", userId, item.Id); - uow.Complete(); + Audit(AuditType.Save, $"Save {typeof(TItem).Name} performed by user", userId, item.Id); + scope.Complete(); } } @@ -426,43 +419,41 @@ namespace Umbraco.Core.Services { var itemsA = items.ToArray(); - using (var uow = UowProvider.CreateUnitOfWork()) + using (var scope = ScopeProvider.CreateScope()) { var saveEventArgs = new SaveEventArgs(itemsA); - if (OnSavingCancelled(uow, saveEventArgs)) + if (OnSavingCancelled(scope, saveEventArgs)) { - uow.Complete(); + scope.Complete(); return; } - var repo = uow.CreateRepository(); - uow.WriteLock(WriteLockIds); + scope.WriteLock(WriteLockIds); // all-or-nothing, validate them all first foreach (var contentType in itemsA) { - ValidateLocked(repo, contentType); // throws if invalid + ValidateLocked(contentType); // throws if invalid } foreach (var contentType in itemsA) { contentType.CreatorId = userId; if (contentType.Description == string.Empty) contentType.Description = null; - repo.Save(contentType); + Repository.Save(contentType); } // figure out impacted content types var changes = ComposeContentTypeChanges(itemsA).ToArray(); var args = changes.ToEventArgs(); - uow.Flush(); // to db but no commit yet - for uow event OnUowRefreshedEntity(args); - OnChanged(uow, args); + OnChanged(scope, args); saveEventArgs.CanCancel = false; - OnSaved(uow, saveEventArgs); + OnSaved(scope, saveEventArgs); - Audit(uow, AuditType.Save, $"Save {typeof(TItem).Name} performed by user", userId, -1); - uow.Complete(); + Audit(AuditType.Save, $"Save {typeof(TItem).Name} performed by user", userId, -1); + scope.Complete(); } } @@ -472,17 +463,16 @@ namespace Umbraco.Core.Services public void Delete(TItem item, int userId = 0) { - using (var uow = UowProvider.CreateUnitOfWork()) + using (var scope = ScopeProvider.CreateScope()) { var deleteEventArgs = new DeleteEventArgs(item); - if (OnDeletingCancelled(uow, deleteEventArgs)) + if (OnDeletingCancelled(scope, deleteEventArgs)) { - uow.Complete(); + scope.Complete(); return; } - var repo = uow.CreateRepository(); - uow.WriteLock(WriteLockIds); + scope.WriteLock(WriteLockIds); // all descendants are going to be deleted var descendantsAndSelf = GetDescendants(item.Id, true) @@ -506,23 +496,22 @@ namespace Umbraco.Core.Services // (contents of any descendant type have been deleted but // contents of any composed (impacted) type remain but // need to have their property data cleared) - repo.Delete(item); + Repository.Delete(item); //... var changes = descendantsAndSelf.Select(x => new ContentTypeChange(x, ContentTypeChangeTypes.Remove)) .Concat(changed.Select(x => new ContentTypeChange(x, ContentTypeChangeTypes.RefreshMain | ContentTypeChangeTypes.RefreshOther))); var args = changes.ToEventArgs(); - uow.Flush(); // to db but no commit yet - for uow event OnUowRefreshedEntity(args); - OnChanged(uow, args); + OnChanged(scope, args); deleteEventArgs.DeletedEntities = deleted.DistinctBy(x => x.Id); deleteEventArgs.CanCancel = false; - OnDeleted(uow, deleteEventArgs); + OnDeleted(scope, deleteEventArgs); - Audit(uow, AuditType.Delete, $"Delete {typeof(TItem).Name} performed by user", userId, item.Id); - uow.Complete(); + Audit(AuditType.Delete, $"Delete {typeof(TItem).Name} performed by user", userId, item.Id); + scope.Complete(); } } @@ -530,17 +519,16 @@ namespace Umbraco.Core.Services { var itemsA = items.ToArray(); - using (var uow = UowProvider.CreateUnitOfWork()) + using (var scope = ScopeProvider.CreateScope()) { var deleteEventArgs = new DeleteEventArgs(itemsA); - if (OnDeletingCancelled(uow, deleteEventArgs)) + if (OnDeletingCancelled(scope, deleteEventArgs)) { - uow.Complete(); + scope.Complete(); return; } - var repo = uow.CreateRepository(); - uow.WriteLock(WriteLockIds); + scope.WriteLock(WriteLockIds); // all descendants are going to be deleted var allDescendantsAndSelf = itemsA.SelectMany(xx => GetDescendants(xx.Id, true)) @@ -562,22 +550,21 @@ namespace Umbraco.Core.Services // finally delete the content types // (see notes in overload) foreach (var item in itemsA) - repo.Delete(item); + Repository.Delete(item); var changes = allDescendantsAndSelf.Select(x => new ContentTypeChange(x, ContentTypeChangeTypes.Remove)) .Concat(changed.Select(x => new ContentTypeChange(x, ContentTypeChangeTypes.RefreshMain | ContentTypeChangeTypes.RefreshOther))); var args = changes.ToEventArgs(); - uow.Flush(); // to db but no commit yet - for uow event OnUowRefreshedEntity(args); - OnChanged(uow, args); + OnChanged(scope, args); deleteEventArgs.DeletedEntities = deleted.DistinctBy(x => x.Id); deleteEventArgs.CanCancel = false; - OnDeleted(uow, deleteEventArgs); + OnDeleted(scope, deleteEventArgs); - Audit(uow, AuditType.Delete, $"Delete {typeof(TItem).Name} performed by user", userId, -1); - uow.Complete(); + Audit(AuditType.Delete, $"Delete {typeof(TItem).Name} performed by user", userId, -1); + scope.Complete(); } } @@ -646,21 +633,19 @@ namespace Umbraco.Core.Services var evtMsgs = EventMessagesFactory.Get(); TItem copy; - using (var uow = UowProvider.CreateUnitOfWork()) + using (var scope = ScopeProvider.CreateScope()) { - var repo = uow.CreateRepository(); - uow.WriteLock(WriteLockIds); + scope.WriteLock(WriteLockIds); - var containerRepository = uow.CreateContainerRepository(ContainerObjectType); try { if (containerId > 0) { - var container = containerRepository.Get(containerId); + var container = _containerRepository.Get(containerId); if (container == null) throw new DataOperationException(MoveOperationStatusType.FailedParentNotFound); // causes rollback } - var alias = repo.GetUniqueAlias(copying.Alias); + var alias = Repository.GetUniqueAlias(copying.Alias); // this is illegal //var copyingb = (ContentTypeCompositionBase) copying; @@ -674,14 +659,14 @@ namespace Umbraco.Core.Services // all other compositions remain in place in the copied content type if (copy.ParentId > 0) { - var parent = repo.Get(copy.ParentId); + var parent = Repository.Get(copy.ParentId); if (parent != null) copy.RemoveContentType(parent.Alias); } copy.ParentId = containerId; - repo.Save(copy); - uow.Complete(); + Repository.Save(copy); + scope.Complete(); } catch (DataOperationException ex) { @@ -701,36 +686,33 @@ namespace Umbraco.Core.Services var evtMsgs = EventMessagesFactory.Get(); var moveInfo = new List>(); - using (var uow = UowProvider.CreateUnitOfWork()) + using (var scope = ScopeProvider.CreateScope()) { var moveEventInfo = new MoveEventInfo(moving, moving.Path, containerId); var moveEventArgs = new MoveEventArgs(evtMsgs, moveEventInfo); - if (OnMovingCancelled(uow, moveEventArgs)) + if (OnMovingCancelled(scope, moveEventArgs)) { - uow.Complete(); + scope.Complete(); return OperationResult.Attempt.Fail(MoveOperationStatusType.FailedCancelledByEvent, evtMsgs); } - uow.WriteLock(WriteLockIds); // also for containers - - var repo = uow.CreateRepository(); - var containerRepo = uow.CreateRepository(); + scope.WriteLock(WriteLockIds); // also for containers try { EntityContainer container = null; if (containerId > 0) { - container = containerRepo.Get(containerId); + container = _containerRepository.Get(containerId); if (container == null) throw new DataOperationException(MoveOperationStatusType.FailedParentNotFound); // causes rollback } - moveInfo.AddRange(repo.Move(moving, container)); - uow.Complete(); + moveInfo.AddRange(Repository.Move(moving, container)); + scope.Complete(); } catch (DataOperationException ex) { - uow.Complete(); + scope.Complete(); return OperationResult.Attempt.Fail(ex.Operation, evtMsgs); } @@ -740,7 +722,7 @@ namespace Umbraco.Core.Services moveEventArgs.MoveInfoCollection = moveInfo; moveEventArgs.CanCancel = false; - OnMoved(uow, moveEventArgs); + OnMoved(scope, moveEventArgs); } return OperationResult.Attempt.Succeed(MoveOperationStatusType.Success, evtMsgs); @@ -757,11 +739,10 @@ namespace Umbraco.Core.Services public Attempt> CreateContainer(int parentId, string name, int userId = 0) { var evtMsgs = EventMessagesFactory.Get(); - using (var uow = UowProvider.CreateUnitOfWork()) + using (var scope = ScopeProvider.CreateScope()) { - uow.WriteLock(WriteLockIds); // also for containers + scope.WriteLock(WriteLockIds); // also for containers - var repo = uow.CreateContainerRepository(ContainerObjectType); try { var container = new EntityContainer(Constants.ObjectTypes.DocumentType) @@ -772,24 +753,24 @@ namespace Umbraco.Core.Services }; var saveEventArgs = new SaveEventArgs(container, evtMsgs); - if (OnSavingContainerCancelled(uow, saveEventArgs)) + if (OnSavingContainerCancelled(scope, saveEventArgs)) { - uow.Complete(); + scope.Complete(); return OperationResult.Attempt.Cancel(evtMsgs, container); } - repo.Save(container); - uow.Complete(); + _containerRepository.Save(container); + scope.Complete(); saveEventArgs.CanCancel = false; - OnSavedContainer(uow, saveEventArgs); + OnSavedContainer(scope, saveEventArgs); //TODO: Audit trail ? return OperationResult.Attempt.Succeed(evtMsgs, container); } catch (Exception ex) { - uow.Complete(); + scope.Complete(); return OperationResult.Attempt.Fail(OperationResultType.FailedCancelledByEvent, evtMsgs, ex); } } @@ -812,21 +793,20 @@ namespace Umbraco.Core.Services return OperationResult.Attempt.Fail(evtMsgs, ex); } - using (var uow = UowProvider.CreateUnitOfWork()) + using (var scope = ScopeProvider.CreateScope()) { - if (OnSavingContainerCancelled(uow, new SaveEventArgs(container, evtMsgs))) + if (OnSavingContainerCancelled(scope, new SaveEventArgs(container, evtMsgs))) { - uow.Complete(); + scope.Complete(); return OperationResult.Attempt.Cancel(evtMsgs); } - uow.WriteLock(WriteLockIds); // also for containers + scope.WriteLock(WriteLockIds); // also for containers - var repo = uow.CreateContainerRepository(containerObjectType); - repo.Save(container); - uow.Complete(); + _containerRepository.Save(container); + scope.Complete(); - OnSavedContainer(uow, new SaveEventArgs(container, evtMsgs)); + OnSavedContainer(scope, new SaveEventArgs(container, evtMsgs)); } //TODO: Audit trail ? @@ -836,34 +816,31 @@ namespace Umbraco.Core.Services public EntityContainer GetContainer(int containerId) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - uow.ReadLock(ReadLockIds); // also for containers + scope.ReadLock(ReadLockIds); // also for containers - var repo = uow.CreateContainerRepository(ContainerObjectType); - return repo.Get(containerId); + return _containerRepository.Get(containerId); } } public EntityContainer GetContainer(Guid containerId) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - uow.ReadLock(ReadLockIds); // also for containers + scope.ReadLock(ReadLockIds); // also for containers - var repo = uow.CreateContainerRepository(ContainerObjectType); - return ((EntityContainerRepository) repo).Get(containerId); + return ((EntityContainerRepository) _containerRepository).Get(containerId); } } public IEnumerable GetContainers(int[] containerIds) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - uow.ReadLock(ReadLockIds); // also for containers + scope.ReadLock(ReadLockIds); // also for containers - var repo = uow.CreateContainerRepository(ContainerObjectType); - return repo.GetMany(containerIds); + return _containerRepository.GetMany(containerIds); } } @@ -883,47 +860,44 @@ namespace Umbraco.Core.Services public IEnumerable GetContainers(string name, int level) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - uow.ReadLock(ReadLockIds); // also for containers + scope.ReadLock(ReadLockIds); // also for containers - var repo = uow.CreateContainerRepository(ContainerObjectType); - return ((EntityContainerRepository) repo).Get(name, level); + return ((EntityContainerRepository) _containerRepository).Get(name, level); } } public Attempt DeleteContainer(int containerId, int userId = 0) { var evtMsgs = EventMessagesFactory.Get(); - using (var uow = UowProvider.CreateUnitOfWork()) + using (var scope = ScopeProvider.CreateScope()) { - uow.WriteLock(WriteLockIds); // also for containers + scope.WriteLock(WriteLockIds); // also for containers - var repo = uow.CreateContainerRepository(ContainerObjectType); - var container = repo.Get(containerId); + var container = _containerRepository.Get(containerId); if (container == null) return OperationResult.Attempt.NoOperation(evtMsgs); - var erepo = uow.CreateRepository(); - var entity = erepo.Get(container.Id); + var entity = _entityRepository.Get(container.Id); if (entity.HasChildren()) // fixme because container.HasChildren() does not work? { // fixme - here and everywhere, original v8 would not Complete, thus causing rollback = ? - uow.Complete(); + scope.Complete(); return Attempt.Fail(new OperationResult(OperationResultType.FailedCannot, evtMsgs)); } var deleteEventArgs = new DeleteEventArgs(container, evtMsgs); - if (OnDeletingContainerCancelled(uow, deleteEventArgs)) + if (OnDeletingContainerCancelled(scope, deleteEventArgs)) { - uow.Complete(); + scope.Complete(); return Attempt.Fail(new OperationResult(OperationResultType.FailedCancelledByEvent, evtMsgs)); } - repo.Delete(container); - uow.Complete(); + _containerRepository.Delete(container); + scope.Complete(); deleteEventArgs.CanCancel = false; - OnDeletedContainer(uow, deleteEventArgs); + OnDeletedContainer(scope, deleteEventArgs); return OperationResult.Attempt.Succeed(evtMsgs); //TODO: Audit trail ? @@ -933,24 +907,23 @@ namespace Umbraco.Core.Services public Attempt> RenameContainer(int id, string name, int userId = 0) { var evtMsgs = EventMessagesFactory.Get(); - using (var uow = UowProvider.CreateUnitOfWork()) + using (var scope = ScopeProvider.CreateScope()) { - uow.WriteLock(WriteLockIds); // also for containers + scope.WriteLock(WriteLockIds); // also for containers - var repository = uow.CreateContainerRepository(ContainerObjectType); try { - var container = repository.Get(id); + var container = _containerRepository.Get(id); //throw if null, this will be caught by the catch and a failed returned if (container == null) throw new InvalidOperationException("No container found with id " + id); container.Name = name; - repository.Save(container); - uow.Complete(); + _containerRepository.Save(container); + scope.Complete(); - OnRenamedContainer(uow, new SaveEventArgs(container, evtMsgs)); + OnRenamedContainer(scope, new SaveEventArgs(container, evtMsgs)); return OperationResult.Attempt.Succeed(OperationResultType.Success, evtMsgs, container); } @@ -965,10 +938,9 @@ namespace Umbraco.Core.Services #region Audit - private void Audit(IScopeUnitOfWork uow, AuditType type, string message, int userId, int objectId) + private void Audit(AuditType type, string message, int userId, int objectId) { - var repo = uow.CreateRepository(); - repo.Save(new AuditItem(objectId, message, type, userId)); + _auditRepository.Save(new AuditItem(objectId, message, type, userId)); } #endregion diff --git a/src/Umbraco.Core/Services/DataTypeService.cs b/src/Umbraco.Core/Services/DataTypeService.cs index 3696179f2e..e50dcb2244 100644 --- a/src/Umbraco.Core/Services/DataTypeService.cs +++ b/src/Umbraco.Core/Services/DataTypeService.cs @@ -5,31 +5,42 @@ using Umbraco.Core.Events; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.Rdbms; -using Umbraco.Core.Persistence.UnitOfWork; using Umbraco.Core.PropertyEditors; using Umbraco.Core.Exceptions; using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.Repositories.Implement; +using Umbraco.Core.Scoping; namespace Umbraco.Core.Services { /// /// Represents the DataType Service, which is an easy access to operations involving /// - public class DataTypeService : ScopeRepositoryService, IDataTypeService + internal class DataTypeService : ScopeRepositoryService, IDataTypeService { - public DataTypeService(IScopeUnitOfWorkProvider provider, ILogger logger, IEventMessagesFactory eventMessagesFactory) + private readonly IDataTypeDefinitionRepository _dataTypeDefinitionRepository; + private readonly IDataTypeContainerRepository _dataTypeContainerRepository; + private readonly IAuditRepository _auditRepository; + private readonly IEntityRepository _entityRepository; + + public DataTypeService(IScopeProvider provider, ILogger logger, IEventMessagesFactory eventMessagesFactory, + IDataTypeDefinitionRepository dataTypeDefinitionRepository, IDataTypeContainerRepository dataTypeContainerRepository, + IAuditRepository auditRepository, IEntityRepository entityRepository) : base(provider, logger, eventMessagesFactory) - { } + { + _dataTypeDefinitionRepository = dataTypeDefinitionRepository; + _dataTypeContainerRepository = dataTypeContainerRepository; + _auditRepository = auditRepository; + _entityRepository = entityRepository; + } #region Containers public Attempt> CreateContainer(int parentId, string name, int userId = 0) { var evtMsgs = EventMessagesFactory.Get(); - using (var uow = UowProvider.CreateUnitOfWork()) + using (var scope = ScopeProvider.CreateScope()) { - var repo = uow.CreateRepository(); try { var container = new EntityContainer(Constants.ObjectTypes.DataType) @@ -39,16 +50,16 @@ namespace Umbraco.Core.Services CreatorId = userId }; - if (uow.Events.DispatchCancelable(SavingContainer, this, new SaveEventArgs(container, evtMsgs))) + if (scope.Events.DispatchCancelable(SavingContainer, this, new SaveEventArgs(container, evtMsgs))) { - uow.Complete(); + scope.Complete(); return OperationResult.Attempt.Cancel(evtMsgs, container); } - repo.Save(container); - uow.Complete(); + _dataTypeContainerRepository.Save(container); + scope.Complete(); - uow.Events.Dispatch(SavedContainer, this, new SaveEventArgs(container, evtMsgs)); + scope.Events.Dispatch(SavedContainer, this, new SaveEventArgs(container, evtMsgs)); //TODO: Audit trail ? return OperationResult.Attempt.Succeed(evtMsgs, container); @@ -62,28 +73,25 @@ namespace Umbraco.Core.Services public EntityContainer GetContainer(int containerId) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - var repo = uow.CreateRepository(); - return repo.Get(containerId); + return _dataTypeContainerRepository.Get(containerId); } } public EntityContainer GetContainer(Guid containerId) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - var repo = uow.CreateRepository(); - return ((EntityContainerRepository)repo).Get(containerId); + return ((EntityContainerRepository) _dataTypeContainerRepository).Get(containerId); } } public IEnumerable GetContainers(string name, int level) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - var repo = uow.CreateRepository(); - return ((EntityContainerRepository)repo).Get(name, level); + return ((EntityContainerRepository) _dataTypeContainerRepository).Get(name, level); } } @@ -103,10 +111,9 @@ namespace Umbraco.Core.Services public IEnumerable GetContainers(int[] containerIds) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - var repo = uow.CreateRepository(); - return repo.GetMany(containerIds); + return _dataTypeContainerRepository.GetMany(containerIds); } } @@ -126,19 +133,18 @@ namespace Umbraco.Core.Services return OperationResult.Attempt.Fail(evtMsgs, ex); } - using (var uow = UowProvider.CreateUnitOfWork()) + using (var scope = ScopeProvider.CreateScope()) { - if (uow.Events.DispatchCancelable(SavingContainer, this, new SaveEventArgs(container, evtMsgs))) + if (scope.Events.DispatchCancelable(SavingContainer, this, new SaveEventArgs(container, evtMsgs))) { - uow.Complete(); + scope.Complete(); return OperationResult.Attempt.Cancel(evtMsgs); } - var repo = uow.CreateRepository(); - repo.Save(container); + _dataTypeContainerRepository.Save(container); - uow.Events.Dispatch(SavedContainer, this, new SaveEventArgs(container, evtMsgs)); - uow.Complete(); + scope.Events.Dispatch(SavedContainer, this, new SaveEventArgs(container, evtMsgs)); + scope.Complete(); } //TODO: Audit trail ? @@ -148,27 +154,25 @@ namespace Umbraco.Core.Services public Attempt DeleteContainer(int containerId, int userId = 0) { var evtMsgs = EventMessagesFactory.Get(); - using (var uow = UowProvider.CreateUnitOfWork()) + using (var scope = ScopeProvider.CreateScope()) { - var repo = uow.CreateRepository(); - var container = repo.Get(containerId); + var container = _dataTypeContainerRepository.Get(containerId); if (container == null) return OperationResult.Attempt.NoOperation(evtMsgs); - var erepo = uow.CreateRepository(); - var entity = erepo.Get(container.Id); + var entity = _entityRepository.Get(container.Id); if (entity.HasChildren()) // because container.HasChildren() does not work? return Attempt.Fail(new OperationResult(OperationResultType.FailedCannot, evtMsgs)); // causes rollback - if (uow.Events.DispatchCancelable(DeletingContainer, this, new DeleteEventArgs(container, evtMsgs))) + if (scope.Events.DispatchCancelable(DeletingContainer, this, new DeleteEventArgs(container, evtMsgs))) { - uow.Complete(); + scope.Complete(); return Attempt.Fail(new OperationResult(OperationResultType.FailedCancelledByEvent, evtMsgs)); } - repo.Delete(container); + _dataTypeContainerRepository.Delete(container); - uow.Events.Dispatch(DeletedContainer, this, new DeleteEventArgs(container, evtMsgs)); - uow.Complete(); + scope.Events.Dispatch(DeletedContainer, this, new DeleteEventArgs(container, evtMsgs)); + scope.Complete(); } //TODO: Audit trail ? @@ -178,13 +182,11 @@ namespace Umbraco.Core.Services public Attempt> RenameContainer(int id, string name, int userId = 0) { var evtMsgs = EventMessagesFactory.Get(); - using (var uow = UowProvider.CreateUnitOfWork()) + using (var scope = ScopeProvider.CreateScope()) { - var repository = uow.CreateRepository(); - try { - var container = repository.Get(id); + var container = _dataTypeContainerRepository.Get(id); //throw if null, this will be caught by the catch and a failed returned if (container == null) @@ -192,11 +194,11 @@ namespace Umbraco.Core.Services container.Name = name; - repository.Save(container); - uow.Complete(); + _dataTypeContainerRepository.Save(container); + scope.Complete(); // fixme - triggering SavedContainer with a different name?! - uow.Events.Dispatch(SavedContainer, this, new SaveEventArgs(container, evtMsgs), "RenamedContainer"); + scope.Events.Dispatch(SavedContainer, this, new SaveEventArgs(container, evtMsgs), "RenamedContainer"); return OperationResult.Attempt.Succeed(OperationResultType.Success, evtMsgs, container); } @@ -216,10 +218,9 @@ namespace Umbraco.Core.Services /// public IDataTypeDefinition GetDataTypeDefinitionByName(string name) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - var repository = uow.CreateRepository(); - return repository.Get(Query().Where(x => x.Name == name)).FirstOrDefault(); + return _dataTypeDefinitionRepository.Get(Query().Where(x => x.Name == name)).FirstOrDefault(); } } @@ -230,10 +231,9 @@ namespace Umbraco.Core.Services /// public IDataTypeDefinition GetDataTypeDefinitionById(int id) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - var repository = uow.CreateRepository(); - return repository.Get(id); + return _dataTypeDefinitionRepository.Get(id); } } @@ -244,11 +244,10 @@ namespace Umbraco.Core.Services /// public IDataTypeDefinition GetDataTypeDefinitionById(Guid id) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - var repository = uow.CreateRepository(); var query = Query().Where(x => x.Key == id); - return repository.Get(query).FirstOrDefault(); + return _dataTypeDefinitionRepository.Get(query).FirstOrDefault(); } } @@ -259,11 +258,10 @@ namespace Umbraco.Core.Services /// Collection of objects with a matching contorl id public IEnumerable GetDataTypeDefinitionByPropertyEditorAlias(string propertyEditorAlias) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - var repository = uow.CreateRepository(); var query = Query().Where(x => x.PropertyEditorAlias == propertyEditorAlias); - return repository.Get(query); + return _dataTypeDefinitionRepository.Get(query); } } @@ -274,10 +272,9 @@ namespace Umbraco.Core.Services /// An enumerable list of objects public IEnumerable GetAllDataTypeDefinitions(params int[] ids) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - var repository = uow.CreateRepository(); - return repository.GetMany(ids); + return _dataTypeDefinitionRepository.GetMany(ids); } } @@ -288,10 +285,9 @@ namespace Umbraco.Core.Services /// An enumerable list of string values public IEnumerable GetPreValuesByDataTypeId(int id) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - var repository = uow.CreateRepository(); - var collection = repository.GetPreValuesCollectionByDataTypeId(id); + var collection = _dataTypeDefinitionRepository.GetPreValuesCollectionByDataTypeId(id); //now convert the collection to a string list return collection.FormatAsDictionary() .Select(x => x.Value.Value) @@ -306,10 +302,9 @@ namespace Umbraco.Core.Services /// public PreValueCollection GetPreValuesCollectionByDataTypeId(int id) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - var repository = uow.CreateRepository(); - return repository.GetPreValuesCollectionByDataTypeId(id); + return _dataTypeDefinitionRepository.GetPreValuesCollectionByDataTypeId(id); } } @@ -320,10 +315,9 @@ namespace Umbraco.Core.Services /// PreValue as a string public string GetPreValueAsString(int id) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - var repository = uow.CreateRepository(); - return repository.GetPreValueAsString(id); + return _dataTypeDefinitionRepository.GetPreValueAsString(id); } } @@ -332,38 +326,35 @@ namespace Umbraco.Core.Services var evtMsgs = EventMessagesFactory.Get(); var moveInfo = new List>(); - using (var uow = UowProvider.CreateUnitOfWork()) + using (var scope = ScopeProvider.CreateScope()) { var moveEventInfo = new MoveEventInfo(toMove, toMove.Path, parentId); var moveEventArgs = new MoveEventArgs(evtMsgs, moveEventInfo); - if (uow.Events.DispatchCancelable(Moving, this, moveEventArgs)) + if (scope.Events.DispatchCancelable(Moving, this, moveEventArgs)) { - uow.Complete(); + scope.Complete(); return OperationResult.Attempt.Fail(MoveOperationStatusType.FailedCancelledByEvent, evtMsgs); } - var containerRepository = uow.CreateRepository(); - var repository = uow.CreateRepository(); - try { EntityContainer container = null; if (parentId > 0) { - container = containerRepository.Get(parentId); + container = _dataTypeContainerRepository.Get(parentId); if (container == null) throw new DataOperationException(MoveOperationStatusType.FailedParentNotFound); // causes rollback } - moveInfo.AddRange(repository.Move(toMove, container)); + moveInfo.AddRange(_dataTypeDefinitionRepository.Move(toMove, container)); moveEventArgs.MoveInfoCollection = moveInfo; moveEventArgs.CanCancel = false; - uow.Events.Dispatch(Moved, this, moveEventArgs); - uow.Complete(); + scope.Events.Dispatch(Moved, this, moveEventArgs); + scope.Complete(); } catch (DataOperationException ex) { - uow.Complete(); // fixme what are we doing here exactly? + scope.Complete(); // fixme what are we doing here exactly? return OperationResult.Attempt.Fail(ex.Operation, evtMsgs); } } @@ -380,12 +371,12 @@ namespace Umbraco.Core.Services { dataTypeDefinition.CreatorId = userId; - using (var uow = UowProvider.CreateUnitOfWork()) + using (var scope = ScopeProvider.CreateScope()) { var saveEventArgs = new SaveEventArgs(dataTypeDefinition); - if (uow.Events.DispatchCancelable(Saving, this, saveEventArgs)) + if (scope.Events.DispatchCancelable(Saving, this, saveEventArgs)) { - uow.Complete(); + scope.Complete(); return; } @@ -394,13 +385,12 @@ namespace Umbraco.Core.Services throw new ArgumentException("Cannot save datatype with empty name."); } - var repository = uow.CreateRepository(); - repository.Save(dataTypeDefinition); + _dataTypeDefinitionRepository.Save(dataTypeDefinition); saveEventArgs.CanCancel = false; - uow.Events.Dispatch(Saved, this, saveEventArgs); - Audit(uow, AuditType.Save, "Save DataTypeDefinition performed by user", userId, dataTypeDefinition.Id); - uow.Complete(); + scope.Events.Dispatch(Saved, this, saveEventArgs); + Audit(AuditType.Save, "Save DataTypeDefinition performed by user", userId, dataTypeDefinition.Id); + scope.Complete(); } } @@ -425,29 +415,28 @@ namespace Umbraco.Core.Services var dataTypeDefinitionsA = dataTypeDefinitions.ToArray(); var saveEventArgs = new SaveEventArgs(dataTypeDefinitionsA); - using (var uow = UowProvider.CreateUnitOfWork()) + using (var scope = ScopeProvider.CreateScope()) { - if (raiseEvents && uow.Events.DispatchCancelable(Saving, this, saveEventArgs)) + if (raiseEvents && scope.Events.DispatchCancelable(Saving, this, saveEventArgs)) { - uow.Complete(); + scope.Complete(); return; } - var repository = uow.CreateRepository(); foreach (var dataTypeDefinition in dataTypeDefinitionsA) { dataTypeDefinition.CreatorId = userId; - repository.Save(dataTypeDefinition); + _dataTypeDefinitionRepository.Save(dataTypeDefinition); } if (raiseEvents) { saveEventArgs.CanCancel = false; - uow.Events.Dispatch(Saved, this, saveEventArgs); + scope.Events.Dispatch(Saved, this, saveEventArgs); } - Audit(uow, AuditType.Save, "Save DataTypeDefinition performed by user", userId, -1); + Audit(AuditType.Save, "Save DataTypeDefinition performed by user", userId, -1); - uow.Complete(); + scope.Complete(); } } @@ -461,9 +450,9 @@ namespace Umbraco.Core.Services { //TODO: Should we raise an event here since we are really saving values for the data type? - using (var uow = UowProvider.CreateUnitOfWork()) + using (var scope = ScopeProvider.CreateScope()) { - var sortOrderObj = uow.Database.ExecuteScalar( + var sortOrderObj = scope.Database.ExecuteScalar( "SELECT max(sortorder) FROM cmsDataTypePreValues WHERE datatypeNodeId = @DataTypeId", new { DataTypeId = dataTypeId }); if (sortOrderObj == null || int.TryParse(sortOrderObj.ToString(), out int sortOrder) == false) @@ -472,11 +461,11 @@ namespace Umbraco.Core.Services foreach (var value in values) { var dto = new DataTypePreValueDto { DataTypeNodeId = dataTypeId, Value = value, SortOrder = sortOrder }; - uow.Database.Insert(dto); + scope.Database.Insert(dto); sortOrder++; } - uow.Complete(); + scope.Complete(); } } @@ -511,11 +500,10 @@ namespace Umbraco.Core.Services { //TODO: Should we raise an event here since we are really saving values for the data type? - using (var uow = UowProvider.CreateUnitOfWork()) + using (var scope = ScopeProvider.CreateScope()) { - var repository = uow.CreateRepository(); - repository.AddOrUpdatePreValues(dataTypeDefinition, values); - uow.Complete(); + _dataTypeDefinitionRepository.AddOrUpdatePreValues(dataTypeDefinition, values); + scope.Complete(); } } @@ -527,12 +515,12 @@ namespace Umbraco.Core.Services /// public void SaveDataTypeAndPreValues(IDataTypeDefinition dataTypeDefinition, IDictionary values, int userId = 0) { - using (var uow = UowProvider.CreateUnitOfWork()) + using (var scope = ScopeProvider.CreateScope()) { var saveEventArgs = new SaveEventArgs(dataTypeDefinition); - if (uow.Events.DispatchCancelable(Saving, this, saveEventArgs)) + if (scope.Events.DispatchCancelable(Saving, this, saveEventArgs)) { - uow.Complete(); + scope.Complete(); return; } @@ -542,15 +530,14 @@ namespace Umbraco.Core.Services dataTypeDefinition.CreatorId = userId; - var repository = uow.CreateRepository(); - repository.Save(dataTypeDefinition); // definition - repository.AddOrUpdatePreValues(dataTypeDefinition, values); //prevalues + _dataTypeDefinitionRepository.Save(dataTypeDefinition); // definition + _dataTypeDefinitionRepository.AddOrUpdatePreValues(dataTypeDefinition, values); //prevalues saveEventArgs.CanCancel = false; - uow.Events.Dispatch(Saved, this, saveEventArgs); - Audit(uow, AuditType.Save, "Save DataTypeDefinition performed by user", userId, dataTypeDefinition.Id); + scope.Events.Dispatch(Saved, this, saveEventArgs); + Audit(AuditType.Save, "Save DataTypeDefinition performed by user", userId, dataTypeDefinition.Id); - uow.Complete(); + scope.Complete(); } } @@ -565,30 +552,28 @@ namespace Umbraco.Core.Services /// Optional Id of the user issueing the deletion public void Delete(IDataTypeDefinition dataTypeDefinition, int userId = 0) { - using (var uow = UowProvider.CreateUnitOfWork()) + using (var scope = ScopeProvider.CreateScope()) { var deleteEventArgs = new DeleteEventArgs(dataTypeDefinition); - if (uow.Events.DispatchCancelable(Deleting, this, deleteEventArgs)) + if (scope.Events.DispatchCancelable(Deleting, this, deleteEventArgs)) { - uow.Complete(); + scope.Complete(); return; } - var repository = uow.CreateRepository(); - repository.Delete(dataTypeDefinition); + _dataTypeDefinitionRepository.Delete(dataTypeDefinition); deleteEventArgs.CanCancel = false; - uow.Events.Dispatch(Deleted, this, deleteEventArgs); - Audit(uow, AuditType.Delete, "Delete DataTypeDefinition performed by user", userId, dataTypeDefinition.Id); + scope.Events.Dispatch(Deleted, this, deleteEventArgs); + Audit(AuditType.Delete, "Delete DataTypeDefinition performed by user", userId, dataTypeDefinition.Id); - uow.Complete(); + scope.Complete(); } } - private void Audit(IUnitOfWork uow, AuditType type, string message, int userId, int objectId) + private void Audit(AuditType type, string message, int userId, int objectId) { - var repo = uow.CreateRepository(); - repo.Save(new AuditItem(objectId, message, type, userId)); + _auditRepository.Save(new AuditItem(objectId, message, type, userId)); } #region Event Handlers diff --git a/src/Umbraco.Core/Services/DomainService.cs b/src/Umbraco.Core/Services/DomainService.cs index c57238c032..a7e1cf22f6 100644 --- a/src/Umbraco.Core/Services/DomainService.cs +++ b/src/Umbraco.Core/Services/DomainService.cs @@ -1,29 +1,28 @@ -using System; -using System.Collections.Generic; -using System.Linq; +using System.Collections.Generic; using Umbraco.Core.Events; using Umbraco.Core.Logging; using Umbraco.Core.Models; -using Umbraco.Core.Persistence; -using Umbraco.Core.Persistence.Querying; using Umbraco.Core.Persistence.Repositories; -using Umbraco.Core.Persistence.UnitOfWork; +using Umbraco.Core.Scoping; namespace Umbraco.Core.Services { public class DomainService : ScopeRepositoryService, IDomainService { - public DomainService(IScopeUnitOfWorkProvider provider, ILogger logger, IEventMessagesFactory eventMessagesFactory) + private readonly IDomainRepository _domainRepository; + + public DomainService(IScopeProvider provider, ILogger logger, IEventMessagesFactory eventMessagesFactory, + IDomainRepository domainRepository) : base(provider, logger, eventMessagesFactory) { + _domainRepository = domainRepository; } public bool Exists(string domainName) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - var repo = uow.CreateRepository(); - return repo.Exists(domainName); + return _domainRepository.Exists(domainName); } } @@ -31,21 +30,20 @@ namespace Umbraco.Core.Services { var evtMsgs = EventMessagesFactory.Get(); - using (var uow = UowProvider.CreateUnitOfWork()) + using (var scope = ScopeProvider.CreateScope()) { var deleteEventArgs = new DeleteEventArgs(domain, evtMsgs); - if (uow.Events.DispatchCancelable(Deleting, this, deleteEventArgs)) + if (scope.Events.DispatchCancelable(Deleting, this, deleteEventArgs)) { - uow.Complete(); + scope.Complete(); return OperationResult.Attempt.Cancel(evtMsgs); } - var repository = uow.CreateRepository(); - repository.Delete(domain); - uow.Complete(); + _domainRepository.Delete(domain); + scope.Complete(); deleteEventArgs.CanCancel = false; - uow.Events.Dispatch(Deleted, this, deleteEventArgs); + scope.Events.Dispatch(Deleted, this, deleteEventArgs); } return OperationResult.Attempt.Succeed(evtMsgs); @@ -53,37 +51,33 @@ namespace Umbraco.Core.Services public IDomain GetByName(string name) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - var repository = uow.CreateRepository(); - return repository.GetByName(name); + return _domainRepository.GetByName(name); } } public IDomain GetById(int id) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - var repo = uow.CreateRepository(); - return repo.Get(id); + return _domainRepository.Get(id); } } public IEnumerable GetAll(bool includeWildcards) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - var repo = uow.CreateRepository(); - return repo.GetAll(includeWildcards); + return _domainRepository.GetAll(includeWildcards); } } public IEnumerable GetAssignedDomains(int contentId, bool includeWildcards) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - var repo = uow.CreateRepository(); - return repo.GetAssignedDomains(contentId, includeWildcards); + return _domainRepository.GetAssignedDomains(contentId, includeWildcards); } } @@ -91,20 +85,19 @@ namespace Umbraco.Core.Services { var evtMsgs = EventMessagesFactory.Get(); - using (var uow = UowProvider.CreateUnitOfWork()) + using (var scope = ScopeProvider.CreateScope()) { var saveEventArgs = new SaveEventArgs(domainEntity, evtMsgs); - if (uow.Events.DispatchCancelable(Saving, this, saveEventArgs)) + if (scope.Events.DispatchCancelable(Saving, this, saveEventArgs)) { - uow.Complete(); + scope.Complete(); return OperationResult.Attempt.Cancel(evtMsgs); } - var repository = uow.CreateRepository(); - repository.Save(domainEntity); - uow.Complete(); + _domainRepository.Save(domainEntity); + scope.Complete(); saveEventArgs.CanCancel = false; - uow.Events.Dispatch(Saved, this, saveEventArgs); + scope.Events.Dispatch(Saved, this, saveEventArgs); } return OperationResult.Attempt.Succeed(evtMsgs); diff --git a/src/Umbraco.Core/Services/EntityService.cs b/src/Umbraco.Core/Services/EntityService.cs index 486f4f1424..c230b62b42 100644 --- a/src/Umbraco.Core/Services/EntityService.cs +++ b/src/Umbraco.Core/Services/EntityService.cs @@ -16,24 +16,28 @@ using Umbraco.Core.Persistence.DatabaseModelDefinitions; using Umbraco.Core.Persistence.Querying; using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.UnitOfWork; +using Umbraco.Core.Scoping; namespace Umbraco.Core.Services { public class EntityService : ScopeRepositoryService, IEntityService { + private readonly IEntityRepository _entityRepository; private readonly Dictionary>> _supportedObjectTypes; private IQuery _queryRootEntity; private readonly IdkMap _idkMap; - public EntityService(IScopeUnitOfWorkProvider provider, ILogger logger, IEventMessagesFactory eventMessagesFactory, + public EntityService(IScopeProvider provider, ILogger logger, IEventMessagesFactory eventMessagesFactory, IContentService contentService, IContentTypeService contentTypeService, IMediaService mediaService, IMediaTypeService mediaTypeService, IDataTypeService dataTypeService, IMemberService memberService, IMemberTypeService memberTypeService, IdkMap idkMap, - IRuntimeCacheProvider runtimeCache) + IRuntimeCacheProvider runtimeCache, + IEntityRepository entityRepository) : base(provider, logger, eventMessagesFactory) { _idkMap = idkMap; + _entityRepository = entityRepository; _supportedObjectTypes = new Dictionary>> { @@ -87,10 +91,9 @@ namespace Umbraco.Core.Services { if (loadBaseType) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) - { - var repository = uow.CreateRepository(); - return repository.GetByKey(key); + using (var scope = ScopeProvider.CreateScope(readOnly: true)) + { + return _entityRepository.GetByKey(key); } } @@ -118,10 +121,9 @@ namespace Umbraco.Core.Services { if (loadBaseType) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - var repository = uow.CreateRepository(); - return repository.Get(id); + return _entityRepository.Get(id); } } @@ -138,10 +140,9 @@ namespace Umbraco.Core.Services if (loadBaseType) { var objectTypeId = umbracoObjectType.GetGuid(); - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - var repository = uow.CreateRepository(); - return repository.GetByKey(key, objectTypeId); + return _entityRepository.GetByKey(key, objectTypeId); } } @@ -170,10 +171,9 @@ namespace Umbraco.Core.Services if (loadBaseType) { var objectTypeId = umbracoObjectType.GetGuid(); - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - var repository = uow.CreateRepository(); - return repository.Get(id, objectTypeId); + return _entityRepository.Get(id, objectTypeId); } } @@ -203,10 +203,9 @@ namespace Umbraco.Core.Services { if (loadBaseType) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - var repository = uow.CreateRepository(); - return repository.Get(id); + return _entityRepository.Get(id); } } @@ -225,14 +224,13 @@ namespace Umbraco.Core.Services /// An public virtual IUmbracoEntity GetParent(int id) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - var repository = uow.CreateRepository(); - var entity = repository.Get(id); + var entity = _entityRepository.Get(id); if (entity.ParentId == -1 || entity.ParentId == -20 || entity.ParentId == -21) return null; - return repository.Get(entity.ParentId); + return _entityRepository.Get(entity.ParentId); } } @@ -244,15 +242,14 @@ namespace Umbraco.Core.Services /// An public virtual IUmbracoEntity GetParent(int id, UmbracoObjectTypes umbracoObjectType) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - var repository = uow.CreateRepository(); - var entity = repository.Get(id); + var entity = _entityRepository.Get(id); if (entity.ParentId == -1 || entity.ParentId == -20 || entity.ParentId == -21) return null; var objectTypeId = umbracoObjectType.GetGuid(); - return repository.Get(entity.ParentId, objectTypeId); + return _entityRepository.Get(entity.ParentId, objectTypeId); } } @@ -263,11 +260,10 @@ namespace Umbraco.Core.Services /// An enumerable list of objects public virtual IEnumerable GetChildren(int parentId) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - var repository = uow.CreateRepository(); var query = Query().Where(x => x.ParentId == parentId); - return repository.GetByQuery(query); + return _entityRepository.GetByQuery(query); } } @@ -280,11 +276,10 @@ namespace Umbraco.Core.Services public virtual IEnumerable GetChildren(int parentId, UmbracoObjectTypes umbracoObjectType) { var objectTypeId = umbracoObjectType.GetGuid(); - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - var repository = uow.CreateRepository(); var query = Query().Where(x => x.ParentId == parentId); - return repository.GetByQuery(query, objectTypeId).ToList(); // run within using! + return _entityRepository.GetByQuery(query, objectTypeId).ToList(); // run within using! // run within using! } } @@ -295,13 +290,12 @@ namespace Umbraco.Core.Services /// An enumerable list of objects public virtual IEnumerable GetDescendents(int id) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - var repository = uow.CreateRepository(); - var entity = repository.Get(id); + var entity = _entityRepository.Get(id); var pathMatch = entity.Path + ","; var query = Query().Where(x => x.Path.StartsWith(pathMatch) && x.Id != id); - return repository.GetByQuery(query); + return _entityRepository.GetByQuery(query); } } @@ -314,12 +308,11 @@ namespace Umbraco.Core.Services public virtual IEnumerable GetDescendents(int id, UmbracoObjectTypes umbracoObjectType) { var objectTypeId = umbracoObjectType.GetGuid(); - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - var repository = uow.CreateRepository(); - var entity = repository.Get(id); + var entity = _entityRepository.Get(id); var query = Query().Where(x => x.Path.StartsWith(entity.Path) && x.Id != id); - return repository.GetByQuery(query, objectTypeId); + return _entityRepository.GetByQuery(query, objectTypeId); } } @@ -339,9 +332,8 @@ namespace Umbraco.Core.Services string orderBy = "SortOrder", Direction orderDirection = Direction.Ascending, string filter = "") { var objectTypeId = umbracoObjectType.GetGuid(); - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - var repository = uow.CreateRepository(); var query = Query().Where(x => x.ParentId == parentId && x.Trashed == false); IQuery filterQuery = null; @@ -350,7 +342,7 @@ namespace Umbraco.Core.Services filterQuery = Query().Where(x => x.Name.Contains(filter)); } - var contents = repository.GetPagedResultsByQuery(query, objectTypeId, pageIndex, pageSize, out totalRecords, orderBy, orderDirection, filterQuery); + var contents = _entityRepository.GetPagedResultsByQuery(query, objectTypeId, pageIndex, pageSize, out totalRecords, orderBy, orderDirection, filterQuery); return contents; } } @@ -371,16 +363,16 @@ namespace Umbraco.Core.Services string orderBy = "path", Direction orderDirection = Direction.Ascending, string filter = "") { var objectTypeId = umbracoObjectType.GetGuid(); - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - var repository = uow.CreateRepository(); - var query = Query(); //if the id is System Root, then just get all + //if the id is System Root, then just get all + if (id != Constants.System.Root) { //lookup the path so we can use it in the prefix query below - var itemPaths = repository.GetAllPaths(objectTypeId, id).ToArray(); + var itemPaths = _entityRepository.GetAllPaths(objectTypeId, id).ToArray(); if (itemPaths.Length == 0) { totalRecords = 0; @@ -390,14 +382,13 @@ namespace Umbraco.Core.Services query.Where(x => x.Path.SqlStartsWith(itemPath + ",", TextColumnType.NVarchar)); } - IQuery filterQuery = null; + if (filter.IsNullOrWhiteSpace() == false) { filterQuery = Query().Where(x => x.Name.Contains(filter)); } - - var contents = repository.GetPagedResultsByQuery(query, objectTypeId, pageIndex, pageSize, out totalRecords, orderBy, orderDirection, filterQuery); + var contents = _entityRepository.GetPagedResultsByQuery(query, objectTypeId, pageIndex, pageSize, out totalRecords, orderBy, orderDirection, filterQuery); return contents; } } @@ -415,21 +406,20 @@ namespace Umbraco.Core.Services var objectTypeId = umbracoObjectType.GetGuid(); - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - var repository = uow.CreateRepository(); - var query = Query(); if (idsA.All(x => x != Constants.System.Root)) { //lookup the paths so we can use it in the prefix query below - var itemPaths = repository.GetAllPaths(objectTypeId, idsA).ToArray(); + //lookup the paths so we can use it in the prefix query below + var itemPaths = _entityRepository.GetAllPaths(objectTypeId, idsA).ToArray(); + if (itemPaths.Length == 0) { totalRecords = 0; return Enumerable.Empty(); } - var clauses = new List>>(); foreach (var id in idsA) { @@ -452,7 +442,7 @@ namespace Umbraco.Core.Services filterQuery = Query().Where(x => x.Name.Contains(filter)); } - var contents = repository.GetPagedResultsByQuery(query, objectTypeId, pageIndex, pageSize, out totalRecords, orderBy, orderDirection, filterQuery); + var contents = _entityRepository.GetPagedResultsByQuery(query, objectTypeId, pageIndex, pageSize, out totalRecords, orderBy, orderDirection, filterQuery); return contents; } } @@ -473,24 +463,23 @@ namespace Umbraco.Core.Services string orderBy = "path", Direction orderDirection = Direction.Ascending, string filter = "", bool includeTrashed = true) { var objectTypeId = umbracoObjectType.GetGuid(); - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - var repository = uow.CreateRepository(); - var query = Query(); //don't include trashed if specfied + //don't include trashed if specfied + if (includeTrashed == false) { query.Where(x => x.Trashed == false); } - IQuery filterQuery = null; + if (filter.IsNullOrWhiteSpace() == false) { filterQuery = Query().Where(x => x.Name.Contains(filter)); } - - var contents = repository.GetPagedResultsByQuery(query, objectTypeId, pageIndex, pageSize, out totalRecords, orderBy, orderDirection, filterQuery); + var contents = _entityRepository.GetPagedResultsByQuery(query, objectTypeId, pageIndex, pageSize, out totalRecords, orderBy, orderDirection, filterQuery); return contents; } } @@ -503,10 +492,9 @@ namespace Umbraco.Core.Services public virtual IEnumerable GetRootEntities(UmbracoObjectTypes umbracoObjectType) { var objectTypeId = umbracoObjectType.GetGuid(); - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - var repository = uow.CreateRepository(); - return repository.GetByQuery(QueryRootEntity, objectTypeId); + return _entityRepository.GetByQuery(QueryRootEntity, objectTypeId); } } @@ -540,10 +528,9 @@ namespace Umbraco.Core.Services throw new NotSupportedException("The passed in type is not supported"); var objectTypeId = umbracoObjectType.GetGuid(); - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - var repository = uow.CreateRepository(); - return repository.GetAll(objectTypeId, ids); + return _entityRepository.GetAll(objectTypeId, ids); } } @@ -556,10 +543,9 @@ namespace Umbraco.Core.Services throw new NotSupportedException("The passed in type is not supported"); var objectTypeId = umbracoObjectType.GetGuid(); - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - var repository = uow.CreateRepository(); - return repository.GetAll(objectTypeId, keys); + return _entityRepository.GetAll(objectTypeId, keys); } } @@ -571,10 +557,9 @@ namespace Umbraco.Core.Services throw new NotSupportedException("The passed in type is not supported."); var objectTypeId = umbracoObjectType.GetGuid(); - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - var repository = uow.CreateRepository(); - return repository.GetAllPaths(objectTypeId, ids); + return _entityRepository.GetAllPaths(objectTypeId, ids); } } @@ -586,10 +571,9 @@ namespace Umbraco.Core.Services throw new NotSupportedException("The passed in type is not supported."); var objectTypeId = umbracoObjectType.GetGuid(); - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - var repository = uow.CreateRepository(); - return repository.GetAllPaths(objectTypeId, keys); + return _entityRepository.GetAllPaths(objectTypeId, keys); } } @@ -608,10 +592,9 @@ namespace Umbraco.Core.Services if (typeFullName == null || _supportedObjectTypes.ContainsKey(typeFullName) == false) throw new NotSupportedException("The passed in type is not supported"); - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - var repository = uow.CreateRepository(); - return repository.GetAll(objectTypeId, ids); + return _entityRepository.GetAll(objectTypeId, ids); } } @@ -622,13 +605,13 @@ namespace Umbraco.Core.Services /// public virtual UmbracoObjectTypes GetObjectType(int id) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - var sql = uow.SqlContext.Sql() + var sql = scope.SqlContext.Sql() .Select("nodeObjectType") .From() .Where(x => x.NodeId == id); - var nodeObjectTypeId = uow.Database.ExecuteScalar(sql); + var nodeObjectTypeId = scope.Database.ExecuteScalar(sql); var objectTypeId = nodeObjectTypeId; return UmbracoObjectTypesExtensions.GetUmbracoObjectType(objectTypeId); } @@ -641,13 +624,13 @@ namespace Umbraco.Core.Services /// public virtual UmbracoObjectTypes GetObjectType(Guid key) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - var sql = uow.SqlContext.Sql() + var sql = scope.SqlContext.Sql() .Select("nodeObjectType") .From() .Where(x => x.UniqueId == key); - var nodeObjectTypeId = uow.Database.ExecuteScalar(sql); + var nodeObjectTypeId = scope.Database.ExecuteScalar(sql); var objectTypeId = nodeObjectTypeId; return UmbracoObjectTypesExtensions.GetUmbracoObjectType(objectTypeId); } @@ -700,20 +683,18 @@ namespace Umbraco.Core.Services public bool Exists(Guid key) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) - { - var repository = uow.CreateRepository(); - var exists = repository.Exists(key); + using (var scope = ScopeProvider.CreateScope(readOnly: true)) + { + var exists = _entityRepository.Exists(key); return exists; } } public bool Exists(int id) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) - { - var repository = uow.CreateRepository(); - var exists = repository.Exists(id); + using (var scope = ScopeProvider.CreateScope(readOnly: true)) + { + var exists = _entityRepository.Exists(id); return exists; } } @@ -722,7 +703,7 @@ namespace Umbraco.Core.Services public int ReserveId(Guid key) { NodeDto node; - using (var scope = UowProvider.ScopeProvider.CreateScope()) + using (var scope = ScopeProvider.CreateScope()) { var sql = new Sql("SELECT * FROM umbracoNode WHERE uniqueID=@0 AND nodeObjectType=@1", key, Constants.ObjectTypes.IdReservation); node = scope.Database.SingleOrDefault(sql); diff --git a/src/Umbraco.Core/Services/ExternalLoginService.cs b/src/Umbraco.Core/Services/ExternalLoginService.cs index af3ed2bd09..f0cfa5562e 100644 --- a/src/Umbraco.Core/Services/ExternalLoginService.cs +++ b/src/Umbraco.Core/Services/ExternalLoginService.cs @@ -5,15 +5,20 @@ using Umbraco.Core.Events; using Umbraco.Core.Logging; using Umbraco.Core.Models.Identity; using Umbraco.Core.Persistence.Repositories; -using Umbraco.Core.Persistence.UnitOfWork; +using Umbraco.Core.Scoping; namespace Umbraco.Core.Services { public class ExternalLoginService : ScopeRepositoryService, IExternalLoginService { - public ExternalLoginService(IScopeUnitOfWorkProvider provider, ILogger logger, IEventMessagesFactory eventMessagesFactory) + private readonly IExternalLoginRepository _externalLoginRepository; + + public ExternalLoginService(IScopeProvider provider, ILogger logger, IEventMessagesFactory eventMessagesFactory, + IExternalLoginRepository externalLoginRepository) : base(provider, logger, eventMessagesFactory) - { } + { + _externalLoginRepository = externalLoginRepository; + } /// /// Returns all user logins assigned @@ -22,12 +27,10 @@ namespace Umbraco.Core.Services /// public IEnumerable GetAll(int userId) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - var repo = uow.CreateRepository(); - return repo - .Get(Query().Where(x => x.UserId == userId)) - .ToList(); // ToList is important here, must evaluate within uow! + return _externalLoginRepository.Get(Query().Where(x => x.UserId == userId)) + .ToList(); // ToList is important here, must evaluate within uow! // ToList is important here, must evaluate within uow! } } @@ -39,12 +42,10 @@ namespace Umbraco.Core.Services /// public IEnumerable Find(UserLoginInfo login) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - var repo = uow.CreateRepository(); - return repo - .Get(Query().Where(x => x.ProviderKey == login.ProviderKey && x.LoginProvider == login.LoginProvider)) - .ToList(); // ToList is important here, must evaluate within uow! + return _externalLoginRepository.Get(Query().Where(x => x.ProviderKey == login.ProviderKey && x.LoginProvider == login.LoginProvider)) + .ToList(); // ToList is important here, must evaluate within uow! // ToList is important here, must evaluate within uow! } } @@ -55,11 +56,10 @@ namespace Umbraco.Core.Services /// public void SaveUserLogins(int userId, IEnumerable logins) { - using (var uow = UowProvider.CreateUnitOfWork()) + using (var scope = ScopeProvider.CreateScope()) { - var repo = uow.CreateRepository(); - repo.SaveUserLogins(userId, logins); - uow.Complete(); + _externalLoginRepository.SaveUserLogins(userId, logins); + scope.Complete(); } } @@ -69,11 +69,10 @@ namespace Umbraco.Core.Services /// public void DeleteUserLogins(int userId) { - using (var uow = UowProvider.CreateUnitOfWork()) + using (var scope = ScopeProvider.CreateScope()) { - var repo = uow.CreateRepository(); - repo.DeleteUserLogins(userId); - uow.Complete(); + _externalLoginRepository.DeleteUserLogins(userId); + scope.Complete(); } } } diff --git a/src/Umbraco.Core/Services/FileService.cs b/src/Umbraco.Core/Services/FileService.cs index 6302b686c2..4bda5d394d 100644 --- a/src/Umbraco.Core/Services/FileService.cs +++ b/src/Umbraco.Core/Services/FileService.cs @@ -8,24 +8,42 @@ using Umbraco.Core.Events; using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Models; -using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.Repositories.Implement; -using Umbraco.Core.Persistence.UnitOfWork; +using Umbraco.Core.Scoping; namespace Umbraco.Core.Services { /// /// Represents the File Service, which is an easy access to operations involving objects like Scripts, Stylesheets and Templates /// - public class FileService : ScopeRepositoryService, IFileService + internal class FileService : ScopeRepositoryService, IFileService { + private readonly IStylesheetRepository _stylesheetRepository; + private readonly IScriptRepository _scriptRepository; + private readonly ITemplateRepository _templateRepository; + private readonly IPartialViewRepository _partialViewRepository; + private readonly IPartialViewMacroRepository _partialViewMacroRepository; + private readonly IXsltFileRepository _xsltRepository; + private readonly IAuditRepository _auditRepository; + private const string PartialViewHeader = "@inherits Umbraco.Web.Mvc.UmbracoTemplatePage"; private const string PartialViewMacroHeader = "@inherits Umbraco.Web.Macros.PartialViewMacroPage"; - public FileService(IScopeUnitOfWorkProvider uowProvider, ILogger logger, IEventMessagesFactory eventMessagesFactory) + public FileService(IScopeProvider uowProvider, ILogger logger, IEventMessagesFactory eventMessagesFactory, + IStylesheetRepository stylesheetRepository, IScriptRepository scriptRepository, ITemplateRepository templateRepository, + IPartialViewRepository partialViewRepository, IPartialViewMacroRepository partialViewMacroRepository, + IXsltFileRepository xsltRepository, IAuditRepository auditRepository) : base(uowProvider, logger, eventMessagesFactory) - { } + { + _stylesheetRepository = stylesheetRepository; + _scriptRepository = scriptRepository; + _templateRepository = templateRepository; + _partialViewRepository = partialViewRepository; + _partialViewMacroRepository = partialViewMacroRepository; + _xsltRepository = xsltRepository; + _auditRepository = auditRepository; + } #region Stylesheets @@ -35,10 +53,9 @@ namespace Umbraco.Core.Services /// An enumerable list of objects public IEnumerable GetStylesheets(params string[] names) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - var repository = uow.CreateRepository(); - return repository.GetMany(names); + return _stylesheetRepository.GetMany(names); } } @@ -49,10 +66,9 @@ namespace Umbraco.Core.Services /// A object public Stylesheet GetStylesheetByName(string name) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - var repository = uow.CreateRepository(); - return repository.Get(name); + return _stylesheetRepository.Get(name); } } @@ -63,22 +79,22 @@ namespace Umbraco.Core.Services /// public void SaveStylesheet(Stylesheet stylesheet, int userId = 0) { - using (var uow = UowProvider.CreateUnitOfWork()) + using (var scope = ScopeProvider.CreateScope()) { var saveEventArgs = new SaveEventArgs(stylesheet); - if (uow.Events.DispatchCancelable(SavingStylesheet, this, saveEventArgs)) + if (scope.Events.DispatchCancelable(SavingStylesheet, this, saveEventArgs)) { - uow.Complete(); + scope.Complete(); return; } - var repository = uow.CreateRepository(); - repository.Save(stylesheet); - saveEventArgs.CanCancel = false; - uow.Events.Dispatch(SavedStylesheet, this, saveEventArgs); - Audit(uow, AuditType.Save, "Save Stylesheet performed by user", userId, -1); - uow.Complete(); + _stylesheetRepository.Save(stylesheet); + saveEventArgs.CanCancel = false; + scope.Events.Dispatch(SavedStylesheet, this, saveEventArgs); + + Audit(AuditType.Save, "Save Stylesheet performed by user", userId, -1); + scope.Complete(); } } @@ -89,29 +105,28 @@ namespace Umbraco.Core.Services /// public void DeleteStylesheet(string path, int userId = 0) { - using (var uow = UowProvider.CreateUnitOfWork()) + using (var scope = ScopeProvider.CreateScope()) { - var repository = uow.CreateRepository(); - var stylesheet = repository.Get(path); + var stylesheet = _stylesheetRepository.Get(path); if (stylesheet == null) { - uow.Complete(); + scope.Complete(); return; } var deleteEventArgs = new DeleteEventArgs(stylesheet); - if (uow.Events.DispatchCancelable(DeletingStylesheet, this, deleteEventArgs)) + if (scope.Events.DispatchCancelable(DeletingStylesheet, this, deleteEventArgs)) { - uow.Complete(); - return; // causes rollback + scope.Complete(); + return; // causes rollback // causes rollback } - repository.Delete(stylesheet); + _stylesheetRepository.Delete(stylesheet); deleteEventArgs.CanCancel = false; - uow.Events.Dispatch(DeletedStylesheet, this, deleteEventArgs); + scope.Events.Dispatch(DeletedStylesheet, this, deleteEventArgs); - Audit(uow, AuditType.Delete, "Delete Stylesheet performed by user", userId, -1); - uow.Complete(); + Audit(AuditType.Delete, "Delete Stylesheet performed by user", userId, -1); + scope.Complete(); } } @@ -122,38 +137,34 @@ namespace Umbraco.Core.Services /// True if Stylesheet is valid, otherwise false public bool ValidateStylesheet(Stylesheet stylesheet) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - var repository = uow.CreateRepository(); - return repository.ValidateStylesheet(stylesheet); + return _stylesheetRepository.ValidateStylesheet(stylesheet); } } public Stream GetStylesheetFileContentStream(string filepath) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - var repository = uow.CreateRepository(); - return repository.GetFileContentStream(filepath); + return _stylesheetRepository.GetFileContentStream(filepath); } } public void SetStylesheetFileContent(string filepath, Stream content) { - using (var uow = UowProvider.CreateUnitOfWork()) + using (var scope = ScopeProvider.CreateScope()) { - var repository = uow.CreateRepository(); - repository.SetFileContent(filepath, content); - uow.Complete(); + _stylesheetRepository.SetFileContent(filepath, content); + scope.Complete(); } } public long GetStylesheetFileSize(string filepath) { - using (var uow = UowProvider.CreateUnitOfWork(readOnly: true)) + using (var scope = ScopeProvider.CreateScope(readOnly: true)) { - var repository = uow.CreateRepository(); - return repository.GetFileSize(filepath); + return _stylesheetRepository.GetFileSize(filepath); } } @@ -167,10 +178,9 @@ namespace Umbraco.Core.Services /// An enumerable list of objects public IEnumerable