From 994f91e4967f6bfc7de9eafb62f4ae9f4a9b2d82 Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 19 Jan 2017 15:37:17 +1100 Subject: [PATCH 1/9] Creates IScopeUnitOfWork and IScopeUnitOfWorkProvider as internal along with ScopeRepositoryService which all services inherit from, this is maintaining backwards compat too --- src/Umbraco.Core/Persistence/LockingRepository.cs | 12 ++++++------ .../Persistence/UnitOfWork/IDatabaseUnitOfWork.cs | 5 +++++ .../UnitOfWork/IDatabaseUnitOfWorkProvider.cs | 11 +++++++++++ .../Persistence/UnitOfWork/PetaPocoUnitOfWork.cs | 5 +++-- .../UnitOfWork/PetaPocoUnitOfWorkProvider.cs | 6 ++++-- src/Umbraco.Core/Services/AuditService.cs | 2 +- src/Umbraco.Core/Services/ContentService.cs | 2 +- src/Umbraco.Core/Services/ContentTypeServiceBase.cs | 2 +- src/Umbraco.Core/Services/DataTypeService.cs | 2 +- src/Umbraco.Core/Services/DomainService.cs | 2 +- src/Umbraco.Core/Services/EntityService.cs | 2 +- src/Umbraco.Core/Services/ExternalLoginService.cs | 2 +- src/Umbraco.Core/Services/FileService.cs | 2 +- src/Umbraco.Core/Services/LocalizationService.cs | 2 +- src/Umbraco.Core/Services/MacroService.cs | 2 +- src/Umbraco.Core/Services/MediaService.cs | 2 +- src/Umbraco.Core/Services/MemberGroupService.cs | 2 +- src/Umbraco.Core/Services/MemberService.cs | 2 +- src/Umbraco.Core/Services/MigrationEntryService.cs | 2 +- src/Umbraco.Core/Services/PublicAccessService.cs | 2 +- src/Umbraco.Core/Services/RedirectUrlService.cs | 2 +- src/Umbraco.Core/Services/RelationService.cs | 2 +- src/Umbraco.Core/Services/RepositoryService.cs | 13 +++++++++++++ .../Services/ServerRegistrationService.cs | 8 ++++---- src/Umbraco.Core/Services/TagService.cs | 2 +- src/Umbraco.Core/Services/TaskService.cs | 2 +- src/Umbraco.Core/Services/UserService.cs | 2 +- 27 files changed, 66 insertions(+), 34 deletions(-) diff --git a/src/Umbraco.Core/Persistence/LockingRepository.cs b/src/Umbraco.Core/Persistence/LockingRepository.cs index 09195f8ce6..992c8cb1ad 100644 --- a/src/Umbraco.Core/Persistence/LockingRepository.cs +++ b/src/Umbraco.Core/Persistence/LockingRepository.cs @@ -10,11 +10,11 @@ namespace Umbraco.Core.Persistence internal class LockingRepository where TRepository : IDisposable, IRepository { - private readonly IDatabaseUnitOfWorkProvider _uowProvider; + private readonly IScopeUnitOfWorkProvider _uowProvider; private readonly Func _repositoryFactory; private readonly int[] _readLockIds, _writeLockIds; - public LockingRepository(IDatabaseUnitOfWorkProvider uowProvider, Func repositoryFactory, + public LockingRepository(IScopeUnitOfWorkProvider uowProvider, Func repositoryFactory, IEnumerable readLockIds, IEnumerable writeLockIds) { Mandate.ParameterNotNull(uowProvider, "uowProvider"); @@ -28,7 +28,7 @@ namespace Umbraco.Core.Persistence public void WithReadLocked(Action> action, bool autoCommit = true) { - using (var uow = ((PetaPocoUnitOfWorkProvider) _uowProvider).GetUnitOfWork(IsolationLevel.RepeatableRead)) + using (var uow = _uowProvider.GetUnitOfWork(IsolationLevel.RepeatableRead)) { // getting the database creates a scope and a transaction // the scope is IsolationLevel.RepeatableRead (because UnitOfWork is) @@ -49,7 +49,7 @@ namespace Umbraco.Core.Persistence public TResult WithReadLocked(Func, TResult> func, bool autoCommit = true) { - using (var uow = ((PetaPocoUnitOfWorkProvider) _uowProvider).GetUnitOfWork(IsolationLevel.RepeatableRead)) + using (var uow = _uowProvider.GetUnitOfWork(IsolationLevel.RepeatableRead)) { // getting the database creates a scope and a transaction // the scope is IsolationLevel.RepeatableRead (because UnitOfWork is) @@ -71,7 +71,7 @@ namespace Umbraco.Core.Persistence public void WithWriteLocked(Action> action, bool autoCommit = true) { - using (var uow = ((PetaPocoUnitOfWorkProvider) _uowProvider).GetUnitOfWork(IsolationLevel.RepeatableRead)) + using (var uow = _uowProvider.GetUnitOfWork(IsolationLevel.RepeatableRead)) { // getting the database creates a scope and a transaction // the scope is IsolationLevel.RepeatableRead (because UnitOfWork is) @@ -92,7 +92,7 @@ namespace Umbraco.Core.Persistence public TResult WithWriteLocked(Func, TResult> func, bool autoCommit = true) { - using (var uow = ((PetaPocoUnitOfWorkProvider) _uowProvider).GetUnitOfWork(IsolationLevel.RepeatableRead)) + using (var uow = _uowProvider.GetUnitOfWork(IsolationLevel.RepeatableRead)) { // getting the database creates a scope and a transaction // the scope is IsolationLevel.RepeatableRead (because UnitOfWork is) diff --git a/src/Umbraco.Core/Persistence/UnitOfWork/IDatabaseUnitOfWork.cs b/src/Umbraco.Core/Persistence/UnitOfWork/IDatabaseUnitOfWork.cs index 616009988f..e2e7fc982a 100644 --- a/src/Umbraco.Core/Persistence/UnitOfWork/IDatabaseUnitOfWork.cs +++ b/src/Umbraco.Core/Persistence/UnitOfWork/IDatabaseUnitOfWork.cs @@ -9,4 +9,9 @@ namespace Umbraco.Core.Persistence.UnitOfWork { UmbracoDatabase Database { get; } } + + internal interface IScopeUnitOfWork : IDatabaseUnitOfWork + { + + } } \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/UnitOfWork/IDatabaseUnitOfWorkProvider.cs b/src/Umbraco.Core/Persistence/UnitOfWork/IDatabaseUnitOfWorkProvider.cs index a63299d0a6..c6996df65f 100644 --- a/src/Umbraco.Core/Persistence/UnitOfWork/IDatabaseUnitOfWorkProvider.cs +++ b/src/Umbraco.Core/Persistence/UnitOfWork/IDatabaseUnitOfWorkProvider.cs @@ -1,3 +1,6 @@ +using System.Data; +using Umbraco.Core.Scoping; + namespace Umbraco.Core.Persistence.UnitOfWork { /// @@ -7,4 +10,12 @@ namespace Umbraco.Core.Persistence.UnitOfWork { IDatabaseUnitOfWork GetUnitOfWork(); } + + /// + /// Defines a Unit of Work Provider for working with + /// + internal interface IScopeUnitOfWorkProvider : IDatabaseUnitOfWorkProvider + { + IDatabaseUnitOfWork GetUnitOfWork(IsolationLevel isolationLevel); + } } \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/UnitOfWork/PetaPocoUnitOfWork.cs b/src/Umbraco.Core/Persistence/UnitOfWork/PetaPocoUnitOfWork.cs index 9caf787ddc..2165ec8899 100644 --- a/src/Umbraco.Core/Persistence/UnitOfWork/PetaPocoUnitOfWork.cs +++ b/src/Umbraco.Core/Persistence/UnitOfWork/PetaPocoUnitOfWork.cs @@ -9,8 +9,8 @@ namespace Umbraco.Core.Persistence.UnitOfWork /// /// Represents the Unit of Work implementation for PetaPoco /// - internal class PetaPocoUnitOfWork : DisposableObject, IDatabaseUnitOfWork - { + internal class PetaPocoUnitOfWork : DisposableObject, IScopeUnitOfWork + { private readonly Queue _operations = new Queue(); private readonly IsolationLevel _isolationLevel; private readonly IScopeProvider _scopeProvider; @@ -27,6 +27,7 @@ namespace Umbraco.Core.Persistence.UnitOfWork /// Creates a new unit of work instance /// /// + /// /// /// This should normally not be used directly and should be created with the UnitOfWorkProvider /// diff --git a/src/Umbraco.Core/Persistence/UnitOfWork/PetaPocoUnitOfWorkProvider.cs b/src/Umbraco.Core/Persistence/UnitOfWork/PetaPocoUnitOfWorkProvider.cs index 4d1b638016..72e05b3866 100644 --- a/src/Umbraco.Core/Persistence/UnitOfWork/PetaPocoUnitOfWorkProvider.cs +++ b/src/Umbraco.Core/Persistence/UnitOfWork/PetaPocoUnitOfWorkProvider.cs @@ -6,10 +6,12 @@ using Umbraco.Core.Scoping; namespace Umbraco.Core.Persistence.UnitOfWork { + + /// /// Represents a Unit of Work Provider for creating a /// - public class PetaPocoUnitOfWorkProvider : IDatabaseUnitOfWorkProvider + public class PetaPocoUnitOfWorkProvider : IScopeUnitOfWorkProvider { private readonly IScopeProvider _scopeProvider; @@ -45,7 +47,7 @@ namespace Umbraco.Core.Persistence.UnitOfWork { } /// - /// Constructor accepting an IDatabaseFactory instance + /// Constructor accepting a instance /// /// public PetaPocoUnitOfWorkProvider(IScopeProvider scopeProvider) diff --git a/src/Umbraco.Core/Services/AuditService.cs b/src/Umbraco.Core/Services/AuditService.cs index 3e076084f2..02f7d03426 100644 --- a/src/Umbraco.Core/Services/AuditService.cs +++ b/src/Umbraco.Core/Services/AuditService.cs @@ -7,7 +7,7 @@ using Umbraco.Core.Persistence.UnitOfWork; namespace Umbraco.Core.Services { - public sealed class AuditService : RepositoryService, IAuditService + public sealed class AuditService : ScopeRepositoryService, IAuditService { public AuditService(IDatabaseUnitOfWorkProvider provider, RepositoryFactory repositoryFactory, ILogger logger, IEventMessagesFactory eventMessagesFactory) : base(provider, repositoryFactory, logger, eventMessagesFactory) diff --git a/src/Umbraco.Core/Services/ContentService.cs b/src/Umbraco.Core/Services/ContentService.cs index e0edaa38c4..5751bba542 100644 --- a/src/Umbraco.Core/Services/ContentService.cs +++ b/src/Umbraco.Core/Services/ContentService.cs @@ -29,7 +29,7 @@ namespace Umbraco.Core.Services /// /// Represents the Content Service, which is an easy access to operations involving /// - public class ContentService : RepositoryService, IContentService, IContentServiceOperations + public class ContentService : ScopeRepositoryService, IContentService, IContentServiceOperations { private readonly IPublishingStrategy _publishingStrategy; private readonly EntityXmlSerializer _entitySerializer = new EntityXmlSerializer(); diff --git a/src/Umbraco.Core/Services/ContentTypeServiceBase.cs b/src/Umbraco.Core/Services/ContentTypeServiceBase.cs index df29012b90..41802e74ae 100644 --- a/src/Umbraco.Core/Services/ContentTypeServiceBase.cs +++ b/src/Umbraco.Core/Services/ContentTypeServiceBase.cs @@ -9,7 +9,7 @@ using Umbraco.Core.Persistence.UnitOfWork; namespace Umbraco.Core.Services { - public class ContentTypeServiceBase : RepositoryService + public class ContentTypeServiceBase : ScopeRepositoryService { public ContentTypeServiceBase(IDatabaseUnitOfWorkProvider provider, RepositoryFactory repositoryFactory, ILogger logger, IEventMessagesFactory eventMessagesFactory) : base(provider, repositoryFactory, logger, eventMessagesFactory) diff --git a/src/Umbraco.Core/Services/DataTypeService.cs b/src/Umbraco.Core/Services/DataTypeService.cs index 2cdcfc76d5..801869d078 100644 --- a/src/Umbraco.Core/Services/DataTypeService.cs +++ b/src/Umbraco.Core/Services/DataTypeService.cs @@ -19,7 +19,7 @@ namespace Umbraco.Core.Services /// /// Represents the DataType Service, which is an easy access to operations involving /// - public class DataTypeService : RepositoryService, IDataTypeService + public class DataTypeService : ScopeRepositoryService, IDataTypeService { public DataTypeService(IDatabaseUnitOfWorkProvider provider, RepositoryFactory repositoryFactory, ILogger logger, IEventMessagesFactory eventMessagesFactory) diff --git a/src/Umbraco.Core/Services/DomainService.cs b/src/Umbraco.Core/Services/DomainService.cs index 3ffcb92778..cd96ce08a8 100644 --- a/src/Umbraco.Core/Services/DomainService.cs +++ b/src/Umbraco.Core/Services/DomainService.cs @@ -10,7 +10,7 @@ using Umbraco.Core.Persistence.UnitOfWork; namespace Umbraco.Core.Services { - public class DomainService : RepositoryService, IDomainService + public class DomainService : ScopeRepositoryService, IDomainService { public DomainService(IDatabaseUnitOfWorkProvider provider, RepositoryFactory repositoryFactory, ILogger logger, IEventMessagesFactory eventMessagesFactory) : base(provider, repositoryFactory, logger, eventMessagesFactory) diff --git a/src/Umbraco.Core/Services/EntityService.cs b/src/Umbraco.Core/Services/EntityService.cs index 08b801229e..1e970d61a9 100644 --- a/src/Umbraco.Core/Services/EntityService.cs +++ b/src/Umbraco.Core/Services/EntityService.cs @@ -14,7 +14,7 @@ using Umbraco.Core.Persistence.UnitOfWork; namespace Umbraco.Core.Services { - public class EntityService : RepositoryService, IEntityService + public class EntityService : ScopeRepositoryService, IEntityService { private readonly IRuntimeCacheProvider _runtimeCache; private readonly Dictionary>> _supportedObjectTypes; diff --git a/src/Umbraco.Core/Services/ExternalLoginService.cs b/src/Umbraco.Core/Services/ExternalLoginService.cs index 91ca77872d..0e0604e89a 100644 --- a/src/Umbraco.Core/Services/ExternalLoginService.cs +++ b/src/Umbraco.Core/Services/ExternalLoginService.cs @@ -10,7 +10,7 @@ using Umbraco.Core.Persistence.UnitOfWork; namespace Umbraco.Core.Services { - public class ExternalLoginService : RepositoryService, IExternalLoginService + public class ExternalLoginService : ScopeRepositoryService, IExternalLoginService { public ExternalLoginService(IDatabaseUnitOfWorkProvider provider, RepositoryFactory repositoryFactory, ILogger logger, IEventMessagesFactory eventMessagesFactory) : base(provider, repositoryFactory, logger, eventMessagesFactory) diff --git a/src/Umbraco.Core/Services/FileService.cs b/src/Umbraco.Core/Services/FileService.cs index 6360ad8988..a8ad4b4885 100644 --- a/src/Umbraco.Core/Services/FileService.cs +++ b/src/Umbraco.Core/Services/FileService.cs @@ -18,7 +18,7 @@ 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 : RepositoryService, IFileService + public class FileService : ScopeRepositoryService, IFileService { private readonly IUnitOfWorkProvider _fileUowProvider; diff --git a/src/Umbraco.Core/Services/LocalizationService.cs b/src/Umbraco.Core/Services/LocalizationService.cs index 261db8672b..6f368b69f0 100644 --- a/src/Umbraco.Core/Services/LocalizationService.cs +++ b/src/Umbraco.Core/Services/LocalizationService.cs @@ -16,7 +16,7 @@ namespace Umbraco.Core.Services /// /// Represents the Localization Service, which is an easy access to operations involving and /// - public class LocalizationService : RepositoryService, ILocalizationService + public class LocalizationService : ScopeRepositoryService, ILocalizationService { diff --git a/src/Umbraco.Core/Services/MacroService.cs b/src/Umbraco.Core/Services/MacroService.cs index a6de12ed32..cf0c364a37 100644 --- a/src/Umbraco.Core/Services/MacroService.cs +++ b/src/Umbraco.Core/Services/MacroService.cs @@ -15,7 +15,7 @@ namespace Umbraco.Core.Services /// /// Represents the Macro Service, which is an easy access to operations involving /// - public class MacroService : RepositoryService, IMacroService + public class MacroService : ScopeRepositoryService, IMacroService { public MacroService(IDatabaseUnitOfWorkProvider provider, RepositoryFactory repositoryFactory, ILogger logger, IEventMessagesFactory eventMessagesFactory) diff --git a/src/Umbraco.Core/Services/MediaService.cs b/src/Umbraco.Core/Services/MediaService.cs index f582ef1eaa..b6ab4e60e6 100644 --- a/src/Umbraco.Core/Services/MediaService.cs +++ b/src/Umbraco.Core/Services/MediaService.cs @@ -25,7 +25,7 @@ namespace Umbraco.Core.Services /// /// Represents the Media Service, which is an easy access to operations involving /// - public class MediaService : RepositoryService, IMediaService, IMediaServiceOperations + public class MediaService : ScopeRepositoryService, IMediaService, IMediaServiceOperations { //Support recursive locks because some of the methods that require locking call other methods that require locking. diff --git a/src/Umbraco.Core/Services/MemberGroupService.cs b/src/Umbraco.Core/Services/MemberGroupService.cs index 47b62917fc..87251c5d23 100644 --- a/src/Umbraco.Core/Services/MemberGroupService.cs +++ b/src/Umbraco.Core/Services/MemberGroupService.cs @@ -11,7 +11,7 @@ using Umbraco.Core.Persistence.UnitOfWork; namespace Umbraco.Core.Services { - public class MemberGroupService : RepositoryService, IMemberGroupService + public class MemberGroupService : ScopeRepositoryService, IMemberGroupService { public MemberGroupService(IDatabaseUnitOfWorkProvider provider, RepositoryFactory repositoryFactory, ILogger logger, IEventMessagesFactory eventMessagesFactory) diff --git a/src/Umbraco.Core/Services/MemberService.cs b/src/Umbraco.Core/Services/MemberService.cs index 094539d66e..237ecd6f27 100644 --- a/src/Umbraco.Core/Services/MemberService.cs +++ b/src/Umbraco.Core/Services/MemberService.cs @@ -24,7 +24,7 @@ namespace Umbraco.Core.Services /// /// Represents the MemberService. /// - public class MemberService : RepositoryService, IMemberService + public class MemberService : ScopeRepositoryService, IMemberService { private readonly IMemberGroupService _memberGroupService; private readonly EntityXmlSerializer _entitySerializer = new EntityXmlSerializer(); diff --git a/src/Umbraco.Core/Services/MigrationEntryService.cs b/src/Umbraco.Core/Services/MigrationEntryService.cs index 2bd463c6d0..9a6b312ea2 100644 --- a/src/Umbraco.Core/Services/MigrationEntryService.cs +++ b/src/Umbraco.Core/Services/MigrationEntryService.cs @@ -14,7 +14,7 @@ namespace Umbraco.Core.Services /// /// Manages migration entries in the database /// - public sealed class MigrationEntryService : RepositoryService, IMigrationEntryService + public sealed class MigrationEntryService : ScopeRepositoryService, IMigrationEntryService { public MigrationEntryService(IDatabaseUnitOfWorkProvider provider, RepositoryFactory repositoryFactory, ILogger logger, IEventMessagesFactory eventMessagesFactory) : base(provider, repositoryFactory, logger, eventMessagesFactory) diff --git a/src/Umbraco.Core/Services/PublicAccessService.cs b/src/Umbraco.Core/Services/PublicAccessService.cs index c2eb536bca..d203eef8dc 100644 --- a/src/Umbraco.Core/Services/PublicAccessService.cs +++ b/src/Umbraco.Core/Services/PublicAccessService.cs @@ -11,7 +11,7 @@ using Umbraco.Core.Persistence.UnitOfWork; namespace Umbraco.Core.Services { - public class PublicAccessService : RepositoryService, IPublicAccessService + public class PublicAccessService : ScopeRepositoryService, IPublicAccessService { public PublicAccessService(IDatabaseUnitOfWorkProvider provider, RepositoryFactory repositoryFactory, ILogger logger, IEventMessagesFactory eventMessagesFactory) : base(provider, repositoryFactory, logger, eventMessagesFactory) diff --git a/src/Umbraco.Core/Services/RedirectUrlService.cs b/src/Umbraco.Core/Services/RedirectUrlService.cs index 0283332401..4018fcc316 100644 --- a/src/Umbraco.Core/Services/RedirectUrlService.cs +++ b/src/Umbraco.Core/Services/RedirectUrlService.cs @@ -8,7 +8,7 @@ using Umbraco.Core.Persistence.UnitOfWork; namespace Umbraco.Core.Services { - internal class RedirectUrlService : RepositoryService, IRedirectUrlService + internal class RedirectUrlService : ScopeRepositoryService, IRedirectUrlService { public RedirectUrlService(IDatabaseUnitOfWorkProvider provider, RepositoryFactory repositoryFactory, ILogger logger, IEventMessagesFactory eventMessagesFactory) : base(provider, repositoryFactory, logger, eventMessagesFactory) diff --git a/src/Umbraco.Core/Services/RelationService.cs b/src/Umbraco.Core/Services/RelationService.cs index 69f79e756e..51f7eb8b2a 100644 --- a/src/Umbraco.Core/Services/RelationService.cs +++ b/src/Umbraco.Core/Services/RelationService.cs @@ -11,7 +11,7 @@ using Umbraco.Core.Persistence.UnitOfWork; namespace Umbraco.Core.Services { - public class RelationService : RepositoryService, IRelationService + public class RelationService : ScopeRepositoryService, IRelationService { private readonly IEntityService _entityService; diff --git a/src/Umbraco.Core/Services/RepositoryService.cs b/src/Umbraco.Core/Services/RepositoryService.cs index 88807f0291..b1e0cf7d21 100644 --- a/src/Umbraco.Core/Services/RepositoryService.cs +++ b/src/Umbraco.Core/Services/RepositoryService.cs @@ -6,6 +6,19 @@ using Umbraco.Core.Persistence.UnitOfWork; namespace Umbraco.Core.Services { + public abstract class ScopeRepositoryService : RepositoryService + { + protected ScopeRepositoryService(IDatabaseUnitOfWorkProvider provider, RepositoryFactory repositoryFactory, ILogger logger, IEventMessagesFactory eventMessagesFactory) + : base(provider, repositoryFactory, logger, eventMessagesFactory) + { + var scopeUow = provider as IScopeUnitOfWorkProvider; + if (scopeUow == null) throw new NotSupportedException("The provider type passed in: " + provider.GetType() + " is not of type " + typeof(IScopeUnitOfWorkProvider)); + UowProvider = scopeUow; + } + + internal new IScopeUnitOfWorkProvider UowProvider { get; private set; } + } + /// /// Base service class /// diff --git a/src/Umbraco.Core/Services/ServerRegistrationService.cs b/src/Umbraco.Core/Services/ServerRegistrationService.cs index b2d5ca855e..9e28f9a91c 100644 --- a/src/Umbraco.Core/Services/ServerRegistrationService.cs +++ b/src/Umbraco.Core/Services/ServerRegistrationService.cs @@ -15,9 +15,9 @@ namespace Umbraco.Core.Services /// /// Manages server registrations in the database. /// - public sealed class ServerRegistrationService : RepositoryService, IServerRegistrationService + public sealed class ServerRegistrationService : ScopeRepositoryService, IServerRegistrationService { - private readonly static string CurrentServerIdentityValue = NetworkHelper.MachineName // eg DOMAIN\SERVER + private static readonly string CurrentServerIdentityValue = NetworkHelper.MachineName // eg DOMAIN\SERVER + "/" + HttpRuntime.AppDomainAppId; // eg /LM/S3SVC/11/ROOT private static readonly int[] LockingRepositoryIds = { Constants.Locks.Servers }; @@ -33,11 +33,11 @@ namespace Umbraco.Core.Services /// public ServerRegistrationService(IDatabaseUnitOfWorkProvider uowProvider, RepositoryFactory repositoryFactory, ILogger logger, IEventMessagesFactory eventMessagesFactory) : base(uowProvider, repositoryFactory, logger, eventMessagesFactory) - { + { _lrepo = new LockingRepository(UowProvider, x => RepositoryFactory.CreateServerRegistrationRepository(x), LockingRepositoryIds, LockingRepositoryIds); - } + } /// /// Touches a server to mark it as active; deactivate stale servers. diff --git a/src/Umbraco.Core/Services/TagService.cs b/src/Umbraco.Core/Services/TagService.cs index d3b502e14b..52f127b0a0 100644 --- a/src/Umbraco.Core/Services/TagService.cs +++ b/src/Umbraco.Core/Services/TagService.cs @@ -15,7 +15,7 @@ namespace Umbraco.Core.Services /// /// If there is unpublished content with tags, those tags will not be contained /// - public class TagService : RepositoryService, ITagService + public class TagService : ScopeRepositoryService, ITagService { public TagService(IDatabaseUnitOfWorkProvider provider, RepositoryFactory repositoryFactory, ILogger logger, IEventMessagesFactory eventMessagesFactory) diff --git a/src/Umbraco.Core/Services/TaskService.cs b/src/Umbraco.Core/Services/TaskService.cs index 9845c5ebb9..450ab13ccf 100644 --- a/src/Umbraco.Core/Services/TaskService.cs +++ b/src/Umbraco.Core/Services/TaskService.cs @@ -10,7 +10,7 @@ using Umbraco.Core.Persistence.UnitOfWork; namespace Umbraco.Core.Services { - public class TaskService : RepositoryService, ITaskService + public class TaskService : ScopeRepositoryService, ITaskService { public TaskService(IDatabaseUnitOfWorkProvider provider, RepositoryFactory repositoryFactory, ILogger logger, IEventMessagesFactory eventMessagesFactory) : base(provider, repositoryFactory, logger, eventMessagesFactory) diff --git a/src/Umbraco.Core/Services/UserService.cs b/src/Umbraco.Core/Services/UserService.cs index 8e984d1e5d..beea62acb7 100644 --- a/src/Umbraco.Core/Services/UserService.cs +++ b/src/Umbraco.Core/Services/UserService.cs @@ -18,7 +18,7 @@ namespace Umbraco.Core.Services /// /// Represents the UserService, which is an easy access to operations involving , and eventually Backoffice Users. /// - public class UserService : RepositoryService, IUserService + public class UserService : ScopeRepositoryService, IUserService { //TODO: We need to change the isUpgrading flag to use an app state enum as described here: http://issues.umbraco.org/issue/U4-6816 From 4f5347fa4d372a3286bb88ce57f77f8305995509 Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 19 Jan 2017 16:31:59 +1100 Subject: [PATCH 2/9] Creates IEventManager, IEventDefinition uses explicit implementation and 'new' keyword to force already existing uow providers to be IScopeUnitOfWork, creates extensions for the event manager so there's less work to do to wire it all up --- src/Umbraco.Core/ApplicationContext.cs | 2 +- src/Umbraco.Core/Events/EventDefinition.cs | 70 +++++++++++++++++++ .../Events/EventDefinitionBase.cs | 14 ++++ src/Umbraco.Core/Events/EventExtensions.cs | 40 ++++++++++- .../{MessageType.cs => EventMessageType.cs} | 0 src/Umbraco.Core/Events/IEventDefinition.cs | 11 +++ src/Umbraco.Core/Events/IEventManager.cs | 18 +++++ .../Events/NoScopedEventManager.cs | 34 +++++++++ src/Umbraco.Core/Events/ScopedEventManager.cs | 35 ++++++++++ src/Umbraco.Core/Events/TypedEventHandler.cs | 2 +- .../UnitOfWork/IDatabaseUnitOfWork.cs | 5 -- .../UnitOfWork/IDatabaseUnitOfWorkProvider.cs | 11 --- .../UnitOfWork/IScopeUnitOfWork.cs | 9 +++ .../UnitOfWork/IScopeUnitOfWorkProvider.cs | 14 ++++ .../UnitOfWork/PetaPocoUnitOfWork.cs | 8 ++- .../UnitOfWork/PetaPocoUnitOfWorkProvider.cs | 9 ++- src/Umbraco.Core/Scoping/IScope.cs | 5 ++ src/Umbraco.Core/Scoping/NoScope.cs | 15 +++- src/Umbraco.Core/Scoping/Scope.cs | 12 +++- src/Umbraco.Core/Umbraco.Core.csproj | 10 ++- 20 files changed, 298 insertions(+), 26 deletions(-) create mode 100644 src/Umbraco.Core/Events/EventDefinition.cs create mode 100644 src/Umbraco.Core/Events/EventDefinitionBase.cs rename src/Umbraco.Core/Events/{MessageType.cs => EventMessageType.cs} (100%) create mode 100644 src/Umbraco.Core/Events/IEventDefinition.cs create mode 100644 src/Umbraco.Core/Events/IEventManager.cs create mode 100644 src/Umbraco.Core/Events/NoScopedEventManager.cs create mode 100644 src/Umbraco.Core/Events/ScopedEventManager.cs create mode 100644 src/Umbraco.Core/Persistence/UnitOfWork/IScopeUnitOfWork.cs create mode 100644 src/Umbraco.Core/Persistence/UnitOfWork/IScopeUnitOfWorkProvider.cs diff --git a/src/Umbraco.Core/ApplicationContext.cs b/src/Umbraco.Core/ApplicationContext.cs index 4be0787a31..07d4508279 100644 --- a/src/Umbraco.Core/ApplicationContext.cs +++ b/src/Umbraco.Core/ApplicationContext.cs @@ -164,7 +164,7 @@ namespace Umbraco.Core public static ApplicationContext Current { get; internal set; } // fixme - public IScopeProvider ScopeProvider { get { return DatabaseContext.ScopeProvider; } } + internal IScopeProvider ScopeProvider { get { return DatabaseContext.ScopeProvider; } } /// /// Returns the application wide cache accessor diff --git a/src/Umbraco.Core/Events/EventDefinition.cs b/src/Umbraco.Core/Events/EventDefinition.cs new file mode 100644 index 0000000000..e7da58f0b5 --- /dev/null +++ b/src/Umbraco.Core/Events/EventDefinition.cs @@ -0,0 +1,70 @@ +using System; + +namespace Umbraco.Core.Events +{ + internal class EventDefinition : EventDefinitionBase + { + private readonly EventHandler _trackedEvent; + private readonly object _sender; + private readonly EventArgs _args; + + public EventDefinition(EventHandler trackedEvent, object sender, EventArgs args) + { + _trackedEvent = trackedEvent; + _sender = sender; + _args = args; + } + + public override void RaiseEvent() + { + if (_trackedEvent != null) + { + _trackedEvent(_sender, _args); + } + } + } + + internal class EventDefinition : EventDefinitionBase + { + private readonly EventHandler _trackedEvent; + private readonly object _sender; + private readonly TEventArgs _args; + + public EventDefinition(EventHandler trackedEvent, object sender, TEventArgs args) + { + _trackedEvent = trackedEvent; + _sender = sender; + _args = args; + } + + public override void RaiseEvent() + { + if (_trackedEvent != null) + { + _trackedEvent(_sender, _args); + } + } + } + + internal class EventDefinition : EventDefinitionBase + { + private readonly TypedEventHandler _trackedEvent; + private readonly TSender _sender; + private readonly TEventArgs _args; + + public EventDefinition(TypedEventHandler trackedEvent, TSender sender, TEventArgs args) + { + _trackedEvent = trackedEvent; + _sender = sender; + _args = args; + } + + public override void RaiseEvent() + { + if (_trackedEvent != null) + { + _trackedEvent(_sender, _args); + } + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Events/EventDefinitionBase.cs b/src/Umbraco.Core/Events/EventDefinitionBase.cs new file mode 100644 index 0000000000..4e33a6f6e6 --- /dev/null +++ b/src/Umbraco.Core/Events/EventDefinitionBase.cs @@ -0,0 +1,14 @@ +using System; + +namespace Umbraco.Core.Events +{ + public abstract class EventDefinitionBase : IEventDefinition + { + protected EventDefinitionBase() + { + EventId = Guid.NewGuid(); + } + public Guid EventId { get; private set; } + public abstract void RaiseEvent(); + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Events/EventExtensions.cs b/src/Umbraco.Core/Events/EventExtensions.cs index bd66b605fd..b1ca0143ac 100644 --- a/src/Umbraco.Core/Events/EventExtensions.cs +++ b/src/Umbraco.Core/Events/EventExtensions.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Reflection; +using System.Runtime.CompilerServices; namespace Umbraco.Core.Events { @@ -30,7 +31,23 @@ namespace Umbraco.Core.Events return args.Cancel; } - + + internal static bool IsRaisedEventCancelled( + this TypedEventHandler eventHandler, + TArgs args, + TSender sender, + IEventManager eventManager) + where TArgs : CancellableEventArgs + { + if (eventManager.SupportsEventCancellation) + { + eventManager.TrackEvent(eventHandler, sender, args); + return args.Cancel; + } + + return false; + } + /// /// Raises the event /// @@ -49,8 +66,27 @@ namespace Umbraco.Core.Events eventHandler(sender, args); } + /// + /// Raises/tracks an event with the event manager + /// + /// + /// + /// + /// + /// + /// + internal static void RaiseEvent( + this TypedEventHandler eventHandler, + TArgs args, + TSender sender, + IEventManager eventManager) + where TArgs : EventArgs + { + eventManager.TrackEvent(eventHandler, sender, args); + } + // moves the last handler that was added to an instance event, to first position - public static void PromoteLastHandler(object sender, string eventName) + public static void PromoteLastHandler(object sender, string eventName) { var fieldInfo = sender.GetType().GetField(eventName, BindingFlags.Instance | BindingFlags.NonPublic); if (fieldInfo == null) throw new InvalidOperationException("No event named " + eventName + "."); diff --git a/src/Umbraco.Core/Events/MessageType.cs b/src/Umbraco.Core/Events/EventMessageType.cs similarity index 100% rename from src/Umbraco.Core/Events/MessageType.cs rename to src/Umbraco.Core/Events/EventMessageType.cs diff --git a/src/Umbraco.Core/Events/IEventDefinition.cs b/src/Umbraco.Core/Events/IEventDefinition.cs new file mode 100644 index 0000000000..9d3a6426fa --- /dev/null +++ b/src/Umbraco.Core/Events/IEventDefinition.cs @@ -0,0 +1,11 @@ +using System; + +namespace Umbraco.Core.Events +{ + public interface IEventDefinition + { + Guid EventId { get; } + + void RaiseEvent(); + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Events/IEventManager.cs b/src/Umbraco.Core/Events/IEventManager.cs new file mode 100644 index 0000000000..21339f07b1 --- /dev/null +++ b/src/Umbraco.Core/Events/IEventManager.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; + +namespace Umbraco.Core.Events +{ + public interface IEventManager + { + IEnumerable GetEvents(); + void TrackEvent(EventHandler e, object sender, EventArgs args); + void TrackEvent(EventHandler e, object sender, TEventArgs args); + void TrackEvent(TypedEventHandler e, TSender sender, TEventArgs args); + + /// + /// True or false depending on if the event manager supports event cancellation + /// + bool SupportsEventCancellation { get; } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Events/NoScopedEventManager.cs b/src/Umbraco.Core/Events/NoScopedEventManager.cs new file mode 100644 index 0000000000..35f964bf0a --- /dev/null +++ b/src/Umbraco.Core/Events/NoScopedEventManager.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Umbraco.Core.Events +{ + internal class NoScopedEventManager : IEventManager + { + public void TrackEvent(EventHandler e, object sender, EventArgs args) + { + if (e != null) e(sender, args); + } + + public void TrackEvent(EventHandler e, object sender, TEventArgs args) + { + if (e != null) e(sender, args); + } + + public void TrackEvent(TypedEventHandler e, TSender sender, TEventArgs args) + { + if (e != null) e(sender, args); + } + + public IEnumerable GetEvents() + { + return Enumerable.Empty(); + } + + public bool SupportsEventCancellation + { + get { return true; } + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Events/ScopedEventManager.cs b/src/Umbraco.Core/Events/ScopedEventManager.cs new file mode 100644 index 0000000000..01e2d5e23f --- /dev/null +++ b/src/Umbraco.Core/Events/ScopedEventManager.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; + +namespace Umbraco.Core.Events +{ + internal class ScopedEventManager : IEventManager + { + public void TrackEvent(EventHandler e, object sender, EventArgs args) + { + _tracked.Add(new EventDefinition(e, sender, args)); + } + + public void TrackEvent(EventHandler e, object sender, TEventArgs args) + { + _tracked.Add(new EventDefinition(e, sender, args)); + } + + public void TrackEvent(TypedEventHandler e, TSender sender, TEventArgs args) + { + _tracked.Add(new EventDefinition(e, sender, args)); + } + + public IEnumerable GetEvents() + { + return _tracked; + } + + private readonly List _tracked = new List(); + + public bool SupportsEventCancellation + { + get { return false; } + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Events/TypedEventHandler.cs b/src/Umbraco.Core/Events/TypedEventHandler.cs index a8170190d4..113bb82f7e 100644 --- a/src/Umbraco.Core/Events/TypedEventHandler.cs +++ b/src/Umbraco.Core/Events/TypedEventHandler.cs @@ -2,6 +2,6 @@ using System; namespace Umbraco.Core.Events { - [Serializable] + [Serializable] public delegate void TypedEventHandler(TSender sender, TEventArgs e); } \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/UnitOfWork/IDatabaseUnitOfWork.cs b/src/Umbraco.Core/Persistence/UnitOfWork/IDatabaseUnitOfWork.cs index e2e7fc982a..616009988f 100644 --- a/src/Umbraco.Core/Persistence/UnitOfWork/IDatabaseUnitOfWork.cs +++ b/src/Umbraco.Core/Persistence/UnitOfWork/IDatabaseUnitOfWork.cs @@ -9,9 +9,4 @@ namespace Umbraco.Core.Persistence.UnitOfWork { UmbracoDatabase Database { get; } } - - internal interface IScopeUnitOfWork : IDatabaseUnitOfWork - { - - } } \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/UnitOfWork/IDatabaseUnitOfWorkProvider.cs b/src/Umbraco.Core/Persistence/UnitOfWork/IDatabaseUnitOfWorkProvider.cs index c6996df65f..a63299d0a6 100644 --- a/src/Umbraco.Core/Persistence/UnitOfWork/IDatabaseUnitOfWorkProvider.cs +++ b/src/Umbraco.Core/Persistence/UnitOfWork/IDatabaseUnitOfWorkProvider.cs @@ -1,6 +1,3 @@ -using System.Data; -using Umbraco.Core.Scoping; - namespace Umbraco.Core.Persistence.UnitOfWork { /// @@ -10,12 +7,4 @@ namespace Umbraco.Core.Persistence.UnitOfWork { IDatabaseUnitOfWork GetUnitOfWork(); } - - /// - /// Defines a Unit of Work Provider for working with - /// - internal interface IScopeUnitOfWorkProvider : IDatabaseUnitOfWorkProvider - { - IDatabaseUnitOfWork GetUnitOfWork(IsolationLevel isolationLevel); - } } \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/UnitOfWork/IScopeUnitOfWork.cs b/src/Umbraco.Core/Persistence/UnitOfWork/IScopeUnitOfWork.cs new file mode 100644 index 0000000000..6bc59da9ae --- /dev/null +++ b/src/Umbraco.Core/Persistence/UnitOfWork/IScopeUnitOfWork.cs @@ -0,0 +1,9 @@ +using Umbraco.Core.Events; + +namespace Umbraco.Core.Persistence.UnitOfWork +{ + internal interface IScopeUnitOfWork : IDatabaseUnitOfWork + { + IEventManager EventManager { get; } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/UnitOfWork/IScopeUnitOfWorkProvider.cs b/src/Umbraco.Core/Persistence/UnitOfWork/IScopeUnitOfWorkProvider.cs new file mode 100644 index 0000000000..6cedc56c33 --- /dev/null +++ b/src/Umbraco.Core/Persistence/UnitOfWork/IScopeUnitOfWorkProvider.cs @@ -0,0 +1,14 @@ +using System.Data; +using Umbraco.Core.Scoping; + +namespace Umbraco.Core.Persistence.UnitOfWork +{ + /// + /// Defines a Unit of Work Provider for working with + /// + internal interface IScopeUnitOfWorkProvider : IDatabaseUnitOfWorkProvider + { + new IScopeUnitOfWork GetUnitOfWork(); + IScopeUnitOfWork GetUnitOfWork(IsolationLevel isolationLevel); + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/UnitOfWork/PetaPocoUnitOfWork.cs b/src/Umbraco.Core/Persistence/UnitOfWork/PetaPocoUnitOfWork.cs index 2165ec8899..ac677732c8 100644 --- a/src/Umbraco.Core/Persistence/UnitOfWork/PetaPocoUnitOfWork.cs +++ b/src/Umbraco.Core/Persistence/UnitOfWork/PetaPocoUnitOfWork.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Data; +using Umbraco.Core.Events; using Umbraco.Core.Models.EntityBase; using Umbraco.Core.Scoping; @@ -198,5 +199,10 @@ namespace Umbraco.Core.Persistence.UnitOfWork _scope.Dispose(); _scope = null; } - } + + public IEventManager EventManager + { + get { throw new NotImplementedException(); } + } + } } \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/UnitOfWork/PetaPocoUnitOfWorkProvider.cs b/src/Umbraco.Core/Persistence/UnitOfWork/PetaPocoUnitOfWorkProvider.cs index 72e05b3866..25f85a7ea2 100644 --- a/src/Umbraco.Core/Persistence/UnitOfWork/PetaPocoUnitOfWorkProvider.cs +++ b/src/Umbraco.Core/Persistence/UnitOfWork/PetaPocoUnitOfWorkProvider.cs @@ -72,7 +72,14 @@ namespace Umbraco.Core.Persistence.UnitOfWork return new PetaPocoUnitOfWork(_scopeProvider); } - public IDatabaseUnitOfWork GetUnitOfWork(IsolationLevel isolationLevel) + //explicit implementation + IScopeUnitOfWork IScopeUnitOfWorkProvider.GetUnitOfWork() + { + return new PetaPocoUnitOfWork(_scopeProvider); + } + + //explicit implementation + IScopeUnitOfWork IScopeUnitOfWorkProvider.GetUnitOfWork(IsolationLevel isolationLevel) { return new PetaPocoUnitOfWork(_scopeProvider, isolationLevel); } diff --git a/src/Umbraco.Core/Scoping/IScope.cs b/src/Umbraco.Core/Scoping/IScope.cs index 4960350575..077e7398b2 100644 --- a/src/Umbraco.Core/Scoping/IScope.cs +++ b/src/Umbraco.Core/Scoping/IScope.cs @@ -20,6 +20,11 @@ namespace Umbraco.Core.Scoping /// IList Messages { get; } + /// + /// Gets the event manager + /// + IEventManager EventManager { get; } + /// /// Completes the scope. /// diff --git a/src/Umbraco.Core/Scoping/NoScope.cs b/src/Umbraco.Core/Scoping/NoScope.cs index 5c53e89047..6b8407a8f0 100644 --- a/src/Umbraco.Core/Scoping/NoScope.cs +++ b/src/Umbraco.Core/Scoping/NoScope.cs @@ -14,6 +14,7 @@ namespace Umbraco.Core.Scoping private bool _disposed; private UmbracoDatabase _database; + private IEventManager _eventManager; private IList _messages; public NoScope(ScopeProvider scopeProvider) @@ -57,7 +58,7 @@ namespace Umbraco.Core.Scoping return _messages ?? (_messages = new List()); } } - + public IList MessagesOrNull { get @@ -67,6 +68,16 @@ namespace Umbraco.Core.Scoping } } + /// + public IEventManager EventManager + { + get + { + EnsureNotDisposed(); + return _eventManager ?? (_eventManager = new NoScopedEventManager()); + } + } + /// public void Complete() { @@ -97,6 +108,6 @@ namespace Umbraco.Core.Scoping _disposed = true; GC.SuppressFinalize(this); - } + } } } diff --git a/src/Umbraco.Core/Scoping/Scope.cs b/src/Umbraco.Core/Scoping/Scope.cs index 4979aa6ae1..ba0092b9cb 100644 --- a/src/Umbraco.Core/Scoping/Scope.cs +++ b/src/Umbraco.Core/Scoping/Scope.cs @@ -14,6 +14,7 @@ namespace Umbraco.Core.Scoping { private readonly ScopeProvider _scopeProvider; private readonly IsolationLevel _isolationLevel; + private IEventManager _eventManager; private bool _disposed; private bool? _completed; @@ -154,6 +155,15 @@ namespace Umbraco.Core.Scoping } } + public IEventManager EventManager + { + get + { + EnsureNotDisposed(); + return _eventManager ?? (_eventManager = new ScopedEventManager()); + } + } + /// public void Complete() { @@ -222,6 +232,6 @@ namespace Umbraco.Core.Scoping _database.Dispose(); _database = null; } - } + } } } diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index afa85609d0..cb4a157d18 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -312,14 +312,20 @@ + + + + + + - + @@ -503,6 +509,8 @@ + + From 27eeb383b41d15e3c839596e4d13e211e2bbc8d0 Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 19 Jan 2017 16:51:39 +1100 Subject: [PATCH 3/9] Updates all repos to use IScopeUnitOfWork --- .../Persistence/LockingRepository.cs | 4 +- .../Repositories/AuditRepository.cs | 2 +- .../Repositories/ContentPreviewRepository.cs | 2 +- .../Repositories/ContentRepository.cs | 2 +- .../Repositories/ContentTypeBaseRepository.cs | 2 +- .../Repositories/ContentTypeRepository.cs | 2 +- .../Repositories/ContentXmlRepository.cs | 2 +- .../DataTypeDefinitionRepository.cs | 4 +- .../Repositories/DictionaryRepository.cs | 6 +- .../Repositories/DomainRepository.cs | 2 +- .../Repositories/EntityContainerRepository.cs | 2 +- .../Repositories/ExternalLoginRepository.cs | 2 +- .../Repositories/LanguageRepository.cs | 2 +- .../Repositories/MacroRepository.cs | 2 +- .../Repositories/MediaRepository.cs | 2 +- .../Repositories/MediaTypeRepository.cs | 2 +- .../Repositories/MemberGroupRepository.cs | 8 +-- .../Repositories/MemberRepository.cs | 2 +- .../Repositories/MemberTypeRepository.cs | 2 +- .../Repositories/MigrationEntryRepository.cs | 2 +- .../Repositories/PetaPocoRepositoryBase.cs | 8 +-- .../Repositories/PublicAccessRepository.cs | 2 +- .../Repositories/RecycleBinRepository.cs | 2 +- .../Repositories/RedirectUrlRepository.cs | 2 +- .../Repositories/RelationRepository.cs | 2 +- .../Repositories/RelationTypeRepository.cs | 2 +- .../ServerRegistrationRepository.cs | 2 +- .../Repositories/SimpleGetRepository.cs | 2 +- .../Persistence/Repositories/TagRepository.cs | 2 +- .../Repositories/TaskRepository.cs | 2 +- .../Repositories/TaskTypeRepository.cs | 2 +- .../Repositories/TemplateRepository.cs | 2 +- .../Repositories/UserRepository.cs | 2 +- .../Repositories/UserTypeRepository.cs | 2 +- .../Repositories/VersionableRepositoryBase.cs | 2 +- .../Persistence/RepositoryFactory.cs | 58 +++++++++---------- .../UnitOfWork/IScopeUnitOfWork.cs | 2 +- .../UnitOfWork/IScopeUnitOfWorkProvider.cs | 2 +- .../UnitOfWork/PetaPocoUnitOfWorkProvider.cs | 26 +++------ src/Umbraco.Core/Services/PackagingService.cs | 4 +- .../Services/ServerRegistrationService.cs | 2 +- src/Umbraco.Core/Services/ServiceContext.cs | 4 +- .../Repositories/ContentRepositoryTest.cs | 6 +- .../Repositories/ContentTypeRepositoryTest.cs | 8 +-- .../DataTypeDefinitionRepositoryTest.cs | 4 +- .../Repositories/DictionaryRepositoryTest.cs | 2 +- .../Repositories/DomainRepositoryTest.cs | 2 +- .../Repositories/LanguageRepositoryTest.cs | 2 +- .../Repositories/LockedRepositoryTests.cs | 2 +- .../Repositories/MediaRepositoryTest.cs | 2 +- .../Repositories/MediaTypeRepositoryTest.cs | 4 +- .../Repositories/MemberRepositoryTest.cs | 2 +- .../Repositories/MemberTypeRepositoryTest.cs | 2 +- .../PublicAccessRepositoryTest.cs | 2 +- .../RedirectUrlRepositoryTests.cs | 2 +- .../Repositories/RelationRepositoryTest.cs | 2 +- .../RelationTypeRepositoryTest.cs | 2 +- .../ServerRegistrationRepositoryTest.cs | 2 +- .../Repositories/TagRepositoryTest.cs | 6 +- .../Repositories/TemplateRepositoryTest.cs | 2 +- .../Repositories/UserRepositoryTest.cs | 2 +- .../Repositories/UserTypeRepositoryTest.cs | 2 +- .../Services/ContentServiceTests.cs | 5 +- .../Templates/TemplateRepositoryTests.cs | 2 +- .../Web/Mvc/UmbracoViewPageTests.cs | 2 +- 65 files changed, 123 insertions(+), 132 deletions(-) diff --git a/src/Umbraco.Core/Persistence/LockingRepository.cs b/src/Umbraco.Core/Persistence/LockingRepository.cs index 992c8cb1ad..6d3d5d54c1 100644 --- a/src/Umbraco.Core/Persistence/LockingRepository.cs +++ b/src/Umbraco.Core/Persistence/LockingRepository.cs @@ -11,10 +11,10 @@ namespace Umbraco.Core.Persistence where TRepository : IDisposable, IRepository { private readonly IScopeUnitOfWorkProvider _uowProvider; - private readonly Func _repositoryFactory; + private readonly Func _repositoryFactory; private readonly int[] _readLockIds, _writeLockIds; - public LockingRepository(IScopeUnitOfWorkProvider uowProvider, Func repositoryFactory, + public LockingRepository(IScopeUnitOfWorkProvider uowProvider, Func repositoryFactory, IEnumerable readLockIds, IEnumerable writeLockIds) { Mandate.ParameterNotNull(uowProvider, "uowProvider"); diff --git a/src/Umbraco.Core/Persistence/Repositories/AuditRepository.cs b/src/Umbraco.Core/Persistence/Repositories/AuditRepository.cs index 53ffda9364..d425755579 100644 --- a/src/Umbraco.Core/Persistence/Repositories/AuditRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/AuditRepository.cs @@ -11,7 +11,7 @@ namespace Umbraco.Core.Persistence.Repositories { internal class AuditRepository : PetaPocoRepositoryBase, IAuditRepository { - public AuditRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax) + public AuditRepository(IScopeUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax) : base(work, cache, logger, sqlSyntax) { } diff --git a/src/Umbraco.Core/Persistence/Repositories/ContentPreviewRepository.cs b/src/Umbraco.Core/Persistence/Repositories/ContentPreviewRepository.cs index b368488833..f148334825 100644 --- a/src/Umbraco.Core/Persistence/Repositories/ContentPreviewRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/ContentPreviewRepository.cs @@ -17,7 +17,7 @@ namespace Umbraco.Core.Persistence.Repositories internal class ContentPreviewRepository : PetaPocoRepositoryBase> where TContent : IContentBase { - public ContentPreviewRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax) + public ContentPreviewRepository(IScopeUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax) : base(work, cache, logger, sqlSyntax) { } diff --git a/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs b/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs index 7f3e657dc2..ebc35b997d 100644 --- a/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs @@ -31,7 +31,7 @@ namespace Umbraco.Core.Persistence.Repositories private readonly ContentPreviewRepository _contentPreviewRepository; private readonly ContentXmlRepository _contentXmlRepository; - public ContentRepository(IDatabaseUnitOfWork work, CacheHelper cacheHelper, ILogger logger, ISqlSyntaxProvider syntaxProvider, IContentTypeRepository contentTypeRepository, ITemplateRepository templateRepository, ITagRepository tagRepository, IContentSection contentSection) + public ContentRepository(IScopeUnitOfWork work, CacheHelper cacheHelper, ILogger logger, ISqlSyntaxProvider syntaxProvider, IContentTypeRepository contentTypeRepository, ITemplateRepository templateRepository, ITagRepository tagRepository, IContentSection contentSection) : base(work, cacheHelper, logger, syntaxProvider, contentSection) { if (contentTypeRepository == null) throw new ArgumentNullException("contentTypeRepository"); diff --git a/src/Umbraco.Core/Persistence/Repositories/ContentTypeBaseRepository.cs b/src/Umbraco.Core/Persistence/Repositories/ContentTypeBaseRepository.cs index d86f77168e..508ba06bb1 100644 --- a/src/Umbraco.Core/Persistence/Repositories/ContentTypeBaseRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/ContentTypeBaseRepository.cs @@ -30,7 +30,7 @@ namespace Umbraco.Core.Persistence.Repositories internal abstract class ContentTypeBaseRepository : PetaPocoRepositoryBase, IReadRepository where TEntity : class, IContentTypeComposition { - protected ContentTypeBaseRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax) + protected ContentTypeBaseRepository(IScopeUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax) : base(work, cache, logger, sqlSyntax) { } diff --git a/src/Umbraco.Core/Persistence/Repositories/ContentTypeRepository.cs b/src/Umbraco.Core/Persistence/Repositories/ContentTypeRepository.cs index b7b4ddd583..a46ee942a2 100644 --- a/src/Umbraco.Core/Persistence/Repositories/ContentTypeRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/ContentTypeRepository.cs @@ -25,7 +25,7 @@ namespace Umbraco.Core.Persistence.Repositories { private readonly ITemplateRepository _templateRepository; - public ContentTypeRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax, ITemplateRepository templateRepository) + public ContentTypeRepository(IScopeUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax, ITemplateRepository templateRepository) : base(work, cache, logger, sqlSyntax) { _templateRepository = templateRepository; diff --git a/src/Umbraco.Core/Persistence/Repositories/ContentXmlRepository.cs b/src/Umbraco.Core/Persistence/Repositories/ContentXmlRepository.cs index b242bb34f7..464ae16961 100644 --- a/src/Umbraco.Core/Persistence/Repositories/ContentXmlRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/ContentXmlRepository.cs @@ -17,7 +17,7 @@ namespace Umbraco.Core.Persistence.Repositories internal class ContentXmlRepository : PetaPocoRepositoryBase> where TContent : IContentBase { - public ContentXmlRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax) + public ContentXmlRepository(IScopeUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax) : base(work, cache, logger, sqlSyntax) { } diff --git a/src/Umbraco.Core/Persistence/Repositories/DataTypeDefinitionRepository.cs b/src/Umbraco.Core/Persistence/Repositories/DataTypeDefinitionRepository.cs index a4d71885f8..b121acc96f 100644 --- a/src/Umbraco.Core/Persistence/Repositories/DataTypeDefinitionRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/DataTypeDefinitionRepository.cs @@ -29,7 +29,7 @@ namespace Umbraco.Core.Persistence.Repositories private readonly IContentTypeRepository _contentTypeRepository; private readonly DataTypePreValueRepository _preValRepository; - public DataTypeDefinitionRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax, + public DataTypeDefinitionRepository(IScopeUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax, IContentTypeRepository contentTypeRepository) : base(work, cache, logger, sqlSyntax) { @@ -519,7 +519,7 @@ AND umbracoNode.id <> @id", /// private class DataTypePreValueRepository : PetaPocoRepositoryBase { - public DataTypePreValueRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax) + public DataTypePreValueRepository(IScopeUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax) : base(work, cache, logger, sqlSyntax) { } diff --git a/src/Umbraco.Core/Persistence/Repositories/DictionaryRepository.cs b/src/Umbraco.Core/Persistence/Repositories/DictionaryRepository.cs index 971efc4f2d..87a3d560a9 100644 --- a/src/Umbraco.Core/Persistence/Repositories/DictionaryRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/DictionaryRepository.cs @@ -20,7 +20,7 @@ namespace Umbraco.Core.Persistence.Repositories /// internal class DictionaryRepository : PetaPocoRepositoryBase, IDictionaryRepository { - public DictionaryRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider syntax) + public DictionaryRepository(IScopeUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider syntax) : base(work, cache, logger, syntax) { } @@ -293,7 +293,7 @@ namespace Umbraco.Core.Persistence.Repositories { private readonly DictionaryRepository _dictionaryRepository; - public DictionaryByUniqueIdRepository(DictionaryRepository dictionaryRepository, IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax) + public DictionaryByUniqueIdRepository(DictionaryRepository dictionaryRepository, IScopeUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax) : base(work, cache, logger, sqlSyntax) { _dictionaryRepository = dictionaryRepository; @@ -350,7 +350,7 @@ namespace Umbraco.Core.Persistence.Repositories { private readonly DictionaryRepository _dictionaryRepository; - public DictionaryByKeyRepository(DictionaryRepository dictionaryRepository, IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax) + public DictionaryByKeyRepository(DictionaryRepository dictionaryRepository, IScopeUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax) : base(work, cache, logger, sqlSyntax) { _dictionaryRepository = dictionaryRepository; diff --git a/src/Umbraco.Core/Persistence/Repositories/DomainRepository.cs b/src/Umbraco.Core/Persistence/Repositories/DomainRepository.cs index 7b6cc162a8..0a3767a365 100644 --- a/src/Umbraco.Core/Persistence/Repositories/DomainRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/DomainRepository.cs @@ -18,7 +18,7 @@ namespace Umbraco.Core.Persistence.Repositories internal class DomainRepository : PetaPocoRepositoryBase, IDomainRepository { - public DomainRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax) + public DomainRepository(IScopeUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax) : base(work, cache, logger, sqlSyntax) { } diff --git a/src/Umbraco.Core/Persistence/Repositories/EntityContainerRepository.cs b/src/Umbraco.Core/Persistence/Repositories/EntityContainerRepository.cs index cc13275798..02d1daea39 100644 --- a/src/Umbraco.Core/Persistence/Repositories/EntityContainerRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/EntityContainerRepository.cs @@ -20,7 +20,7 @@ namespace Umbraco.Core.Persistence.Repositories { private readonly Guid _containerObjectType; - public EntityContainerRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax, Guid containerObjectType) + public EntityContainerRepository(IScopeUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax, Guid containerObjectType) : base(work, cache, logger, sqlSyntax) { var allowedContainers = new[] {Constants.ObjectTypes.DocumentTypeContainerGuid, Constants.ObjectTypes.MediaTypeContainerGuid, Constants.ObjectTypes.DataTypeContainerGuid}; diff --git a/src/Umbraco.Core/Persistence/Repositories/ExternalLoginRepository.cs b/src/Umbraco.Core/Persistence/Repositories/ExternalLoginRepository.cs index 7c80bd10b7..fcaee87975 100644 --- a/src/Umbraco.Core/Persistence/Repositories/ExternalLoginRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/ExternalLoginRepository.cs @@ -15,7 +15,7 @@ namespace Umbraco.Core.Persistence.Repositories { internal class ExternalLoginRepository : PetaPocoRepositoryBase, IExternalLoginRepository { - public ExternalLoginRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax) + public ExternalLoginRepository(IScopeUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax) : base(work, cache, logger, sqlSyntax) { } diff --git a/src/Umbraco.Core/Persistence/Repositories/LanguageRepository.cs b/src/Umbraco.Core/Persistence/Repositories/LanguageRepository.cs index f9a8e59cfa..f8b80ed9da 100644 --- a/src/Umbraco.Core/Persistence/Repositories/LanguageRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/LanguageRepository.cs @@ -19,7 +19,7 @@ namespace Umbraco.Core.Persistence.Repositories /// internal class LanguageRepository : PetaPocoRepositoryBase, ILanguageRepository { - public LanguageRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax) + public LanguageRepository(IScopeUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax) : base(work, cache, logger, sqlSyntax) { } diff --git a/src/Umbraco.Core/Persistence/Repositories/MacroRepository.cs b/src/Umbraco.Core/Persistence/Repositories/MacroRepository.cs index 2e1e481219..398a7cbb54 100644 --- a/src/Umbraco.Core/Persistence/Repositories/MacroRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/MacroRepository.cs @@ -17,7 +17,7 @@ namespace Umbraco.Core.Persistence.Repositories internal class MacroRepository : PetaPocoRepositoryBase, IMacroRepository { - public MacroRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax) + public MacroRepository(IScopeUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax) : base(work, cache, logger, sqlSyntax) { } diff --git a/src/Umbraco.Core/Persistence/Repositories/MediaRepository.cs b/src/Umbraco.Core/Persistence/Repositories/MediaRepository.cs index 08c2f7e0be..7b760410e3 100644 --- a/src/Umbraco.Core/Persistence/Repositories/MediaRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/MediaRepository.cs @@ -28,7 +28,7 @@ namespace Umbraco.Core.Persistence.Repositories private readonly ContentXmlRepository _contentXmlRepository; private readonly ContentPreviewRepository _contentPreviewRepository; - public MediaRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax, IMediaTypeRepository mediaTypeRepository, ITagRepository tagRepository, IContentSection contentSection) + public MediaRepository(IScopeUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax, IMediaTypeRepository mediaTypeRepository, ITagRepository tagRepository, IContentSection contentSection) : base(work, cache, logger, sqlSyntax, contentSection) { if (mediaTypeRepository == null) throw new ArgumentNullException("mediaTypeRepository"); diff --git a/src/Umbraco.Core/Persistence/Repositories/MediaTypeRepository.cs b/src/Umbraco.Core/Persistence/Repositories/MediaTypeRepository.cs index 50a89bfd65..bf1b1455ad 100644 --- a/src/Umbraco.Core/Persistence/Repositories/MediaTypeRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/MediaTypeRepository.cs @@ -23,7 +23,7 @@ namespace Umbraco.Core.Persistence.Repositories internal class MediaTypeRepository : ContentTypeBaseRepository, IMediaTypeRepository { - public MediaTypeRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax) + public MediaTypeRepository(IScopeUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax) : base(work, cache, logger, sqlSyntax) { } diff --git a/src/Umbraco.Core/Persistence/Repositories/MemberGroupRepository.cs b/src/Umbraco.Core/Persistence/Repositories/MemberGroupRepository.cs index 2c0e910428..cf972f849a 100644 --- a/src/Umbraco.Core/Persistence/Repositories/MemberGroupRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/MemberGroupRepository.cs @@ -20,7 +20,7 @@ namespace Umbraco.Core.Persistence.Repositories internal class MemberGroupRepository : PetaPocoRepositoryBase, IMemberGroupRepository { - public MemberGroupRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax) + public MemberGroupRepository(IScopeUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax) : base(work, cache, logger, sqlSyntax) { } @@ -159,15 +159,15 @@ namespace Umbraco.Core.Persistence.Repositories Name = roleName }; PersistNewItem(grp); - - if (SavingMemberGroup.IsRaisedEventCancelled(new SaveEventArgs(grp), this)) + + if (SavingMemberGroup.IsRaisedEventCancelled(new SaveEventArgs(grp), this, UnitOfWork.EventManager)) { return null; } transaction.Complete(); - SavedMemberGroup.RaiseEvent(new SaveEventArgs(grp), this); + SavedMemberGroup.RaiseEvent(new SaveEventArgs(grp), this, UnitOfWork.EventManager); return grp; } diff --git a/src/Umbraco.Core/Persistence/Repositories/MemberRepository.cs b/src/Umbraco.Core/Persistence/Repositories/MemberRepository.cs index dcab898685..2902b3e959 100644 --- a/src/Umbraco.Core/Persistence/Repositories/MemberRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/MemberRepository.cs @@ -29,7 +29,7 @@ namespace Umbraco.Core.Persistence.Repositories private readonly ContentXmlRepository _contentXmlRepository; private readonly ContentPreviewRepository _contentPreviewRepository; - public MemberRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax, IMemberTypeRepository memberTypeRepository, IMemberGroupRepository memberGroupRepository, ITagRepository tagRepository, IContentSection contentSection) + public MemberRepository(IScopeUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax, IMemberTypeRepository memberTypeRepository, IMemberGroupRepository memberGroupRepository, ITagRepository tagRepository, IContentSection contentSection) : base(work, cache, logger, sqlSyntax, contentSection) { if (memberTypeRepository == null) throw new ArgumentNullException("memberTypeRepository"); diff --git a/src/Umbraco.Core/Persistence/Repositories/MemberTypeRepository.cs b/src/Umbraco.Core/Persistence/Repositories/MemberTypeRepository.cs index 7d5defe8c9..dbfdc48ad8 100644 --- a/src/Umbraco.Core/Persistence/Repositories/MemberTypeRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/MemberTypeRepository.cs @@ -22,7 +22,7 @@ namespace Umbraco.Core.Persistence.Repositories internal class MemberTypeRepository : ContentTypeBaseRepository, IMemberTypeRepository { - public MemberTypeRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax) + public MemberTypeRepository(IScopeUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax) : base(work, cache, logger, sqlSyntax) { } diff --git a/src/Umbraco.Core/Persistence/Repositories/MigrationEntryRepository.cs b/src/Umbraco.Core/Persistence/Repositories/MigrationEntryRepository.cs index b4a21f5d21..bd5db622d6 100644 --- a/src/Umbraco.Core/Persistence/Repositories/MigrationEntryRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/MigrationEntryRepository.cs @@ -14,7 +14,7 @@ namespace Umbraco.Core.Persistence.Repositories { internal class MigrationEntryRepository : PetaPocoRepositoryBase, IMigrationEntryRepository { - public MigrationEntryRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax) + public MigrationEntryRepository(IScopeUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax) : base(work, cache, logger, sqlSyntax) { } diff --git a/src/Umbraco.Core/Persistence/Repositories/PetaPocoRepositoryBase.cs b/src/Umbraco.Core/Persistence/Repositories/PetaPocoRepositoryBase.cs index fe363fea16..193cdb6b53 100644 --- a/src/Umbraco.Core/Persistence/Repositories/PetaPocoRepositoryBase.cs +++ b/src/Umbraco.Core/Persistence/Repositories/PetaPocoRepositoryBase.cs @@ -20,7 +20,7 @@ namespace Umbraco.Core.Persistence.Repositories { public ISqlSyntaxProvider SqlSyntax { get; private set; } - protected PetaPocoRepositoryBase(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax) + protected PetaPocoRepositoryBase(IScopeUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax) : base(work, cache, logger) { if (sqlSyntax == null) throw new ArgumentNullException("sqlSyntax"); @@ -28,11 +28,11 @@ namespace Umbraco.Core.Persistence.Repositories } /// - /// Returns the database Unit of Work added to the repository + /// Returns the Scope Unit of Work added to the repository /// - protected internal new IDatabaseUnitOfWork UnitOfWork + protected internal new IScopeUnitOfWork UnitOfWork { - get { return (IDatabaseUnitOfWork)base.UnitOfWork; } + get { return (IScopeUnitOfWork)base.UnitOfWork; } } protected UmbracoDatabase Database diff --git a/src/Umbraco.Core/Persistence/Repositories/PublicAccessRepository.cs b/src/Umbraco.Core/Persistence/Repositories/PublicAccessRepository.cs index 37200b2172..6f9ac12669 100644 --- a/src/Umbraco.Core/Persistence/Repositories/PublicAccessRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/PublicAccessRepository.cs @@ -15,7 +15,7 @@ namespace Umbraco.Core.Persistence.Repositories { internal class PublicAccessRepository : PetaPocoRepositoryBase, IPublicAccessRepository { - public PublicAccessRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax) + public PublicAccessRepository(IScopeUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax) : base(work, cache, logger, sqlSyntax) { } diff --git a/src/Umbraco.Core/Persistence/Repositories/RecycleBinRepository.cs b/src/Umbraco.Core/Persistence/Repositories/RecycleBinRepository.cs index f17a0dd0d2..e5f93d3111 100644 --- a/src/Umbraco.Core/Persistence/Repositories/RecycleBinRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/RecycleBinRepository.cs @@ -18,7 +18,7 @@ namespace Umbraco.Core.Persistence.Repositories internal abstract class RecycleBinRepository : VersionableRepositoryBase, IRecycleBinRepository where TEntity : class, IUmbracoEntity { - protected RecycleBinRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax, IContentSection contentSection) + protected RecycleBinRepository(IScopeUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax, IContentSection contentSection) : base(work, cache, logger, sqlSyntax, contentSection) { } diff --git a/src/Umbraco.Core/Persistence/Repositories/RedirectUrlRepository.cs b/src/Umbraco.Core/Persistence/Repositories/RedirectUrlRepository.cs index 5452e868a0..acab12a10a 100644 --- a/src/Umbraco.Core/Persistence/Repositories/RedirectUrlRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/RedirectUrlRepository.cs @@ -14,7 +14,7 @@ namespace Umbraco.Core.Persistence.Repositories { internal class RedirectUrlRepository : PetaPocoRepositoryBase, IRedirectUrlRepository { - public RedirectUrlRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax) + public RedirectUrlRepository(IScopeUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax) : base(work, cache, logger, sqlSyntax) { } diff --git a/src/Umbraco.Core/Persistence/Repositories/RelationRepository.cs b/src/Umbraco.Core/Persistence/Repositories/RelationRepository.cs index 4511ebe35d..69caaa78af 100644 --- a/src/Umbraco.Core/Persistence/Repositories/RelationRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/RelationRepository.cs @@ -20,7 +20,7 @@ namespace Umbraco.Core.Persistence.Repositories { private readonly IRelationTypeRepository _relationTypeRepository; - public RelationRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax, IRelationTypeRepository relationTypeRepository) + public RelationRepository(IScopeUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax, IRelationTypeRepository relationTypeRepository) : base(work, cache, logger, sqlSyntax) { _relationTypeRepository = relationTypeRepository; diff --git a/src/Umbraco.Core/Persistence/Repositories/RelationTypeRepository.cs b/src/Umbraco.Core/Persistence/Repositories/RelationTypeRepository.cs index 2c54897ff7..104c66557a 100644 --- a/src/Umbraco.Core/Persistence/Repositories/RelationTypeRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/RelationTypeRepository.cs @@ -19,7 +19,7 @@ namespace Umbraco.Core.Persistence.Repositories /// internal class RelationTypeRepository : PetaPocoRepositoryBase, IRelationTypeRepository { - public RelationTypeRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax) + public RelationTypeRepository(IScopeUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax) : base(work, cache, logger, sqlSyntax) { } diff --git a/src/Umbraco.Core/Persistence/Repositories/ServerRegistrationRepository.cs b/src/Umbraco.Core/Persistence/Repositories/ServerRegistrationRepository.cs index 02794ef1fb..5929476509 100644 --- a/src/Umbraco.Core/Persistence/Repositories/ServerRegistrationRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/ServerRegistrationRepository.cs @@ -17,7 +17,7 @@ namespace Umbraco.Core.Persistence.Repositories { private readonly ICacheProvider _staticCache; - public ServerRegistrationRepository(IDatabaseUnitOfWork work, ICacheProvider staticCache, ILogger logger, ISqlSyntaxProvider sqlSyntax) + public ServerRegistrationRepository(IScopeUnitOfWork work, ICacheProvider staticCache, ILogger logger, ISqlSyntaxProvider sqlSyntax) : base(work, CacheHelper.CreateDisabledCacheHelper(), logger, sqlSyntax) { _staticCache = staticCache; diff --git a/src/Umbraco.Core/Persistence/Repositories/SimpleGetRepository.cs b/src/Umbraco.Core/Persistence/Repositories/SimpleGetRepository.cs index a88672ea6f..67c9149422 100644 --- a/src/Umbraco.Core/Persistence/Repositories/SimpleGetRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/SimpleGetRepository.cs @@ -18,7 +18,7 @@ namespace Umbraco.Core.Persistence.Repositories where TDto: class { - protected SimpleGetRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax) + protected SimpleGetRepository(IScopeUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax) : base(work, cache, logger, sqlSyntax) { } diff --git a/src/Umbraco.Core/Persistence/Repositories/TagRepository.cs b/src/Umbraco.Core/Persistence/Repositories/TagRepository.cs index 142740e9d8..0456e16bf3 100644 --- a/src/Umbraco.Core/Persistence/Repositories/TagRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/TagRepository.cs @@ -15,7 +15,7 @@ namespace Umbraco.Core.Persistence.Repositories { internal class TagRepository : PetaPocoRepositoryBase, ITagRepository { - internal TagRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax) + internal TagRepository(IScopeUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax) : base(work, cache, logger, sqlSyntax) { } diff --git a/src/Umbraco.Core/Persistence/Repositories/TaskRepository.cs b/src/Umbraco.Core/Persistence/Repositories/TaskRepository.cs index c02362f8fd..f90e81428b 100644 --- a/src/Umbraco.Core/Persistence/Repositories/TaskRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/TaskRepository.cs @@ -15,7 +15,7 @@ namespace Umbraco.Core.Persistence.Repositories { internal class TaskRepository : PetaPocoRepositoryBase, ITaskRepository { - public TaskRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax) + public TaskRepository(IScopeUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax) : base(work, cache, logger, sqlSyntax) { } diff --git a/src/Umbraco.Core/Persistence/Repositories/TaskTypeRepository.cs b/src/Umbraco.Core/Persistence/Repositories/TaskTypeRepository.cs index a970880669..71c3d2d1a4 100644 --- a/src/Umbraco.Core/Persistence/Repositories/TaskTypeRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/TaskTypeRepository.cs @@ -13,7 +13,7 @@ namespace Umbraco.Core.Persistence.Repositories { internal class TaskTypeRepository : PetaPocoRepositoryBase, ITaskTypeRepository { - public TaskTypeRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax) + public TaskTypeRepository(IScopeUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax) : base(work, cache, logger, sqlSyntax) { } diff --git a/src/Umbraco.Core/Persistence/Repositories/TemplateRepository.cs b/src/Umbraco.Core/Persistence/Repositories/TemplateRepository.cs index 41743601fb..bb1b4a2515 100644 --- a/src/Umbraco.Core/Persistence/Repositories/TemplateRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/TemplateRepository.cs @@ -34,7 +34,7 @@ namespace Umbraco.Core.Persistence.Repositories private readonly ViewHelper _viewHelper; private readonly MasterPageHelper _masterPageHelper; - internal TemplateRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax, IFileSystem masterpageFileSystem, IFileSystem viewFileSystem, ITemplatesSection templateConfig) + internal TemplateRepository(IScopeUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax, IFileSystem masterpageFileSystem, IFileSystem viewFileSystem, ITemplatesSection templateConfig) : base(work, cache, logger, sqlSyntax) { _masterpagesFileSystem = masterpageFileSystem; diff --git a/src/Umbraco.Core/Persistence/Repositories/UserRepository.cs b/src/Umbraco.Core/Persistence/Repositories/UserRepository.cs index 4652ce47be..bad4af0ebc 100644 --- a/src/Umbraco.Core/Persistence/Repositories/UserRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/UserRepository.cs @@ -26,7 +26,7 @@ namespace Umbraco.Core.Persistence.Repositories private readonly IUserTypeRepository _userTypeRepository; private readonly CacheHelper _cacheHelper; - public UserRepository(IDatabaseUnitOfWork work, CacheHelper cacheHelper, ILogger logger, ISqlSyntaxProvider sqlSyntax, IUserTypeRepository userTypeRepository) + public UserRepository(IScopeUnitOfWork work, CacheHelper cacheHelper, ILogger logger, ISqlSyntaxProvider sqlSyntax, IUserTypeRepository userTypeRepository) : base(work, cacheHelper, logger, sqlSyntax) { _userTypeRepository = userTypeRepository; diff --git a/src/Umbraco.Core/Persistence/Repositories/UserTypeRepository.cs b/src/Umbraco.Core/Persistence/Repositories/UserTypeRepository.cs index 1fd94ca357..81e3a5765e 100644 --- a/src/Umbraco.Core/Persistence/Repositories/UserTypeRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/UserTypeRepository.cs @@ -17,7 +17,7 @@ namespace Umbraco.Core.Persistence.Repositories /// internal class UserTypeRepository : PetaPocoRepositoryBase, IUserTypeRepository { - public UserTypeRepository(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax) + public UserTypeRepository(IScopeUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax) : base(work, cache, logger, sqlSyntax) { } diff --git a/src/Umbraco.Core/Persistence/Repositories/VersionableRepositoryBase.cs b/src/Umbraco.Core/Persistence/Repositories/VersionableRepositoryBase.cs index 163e0810ad..712959b072 100644 --- a/src/Umbraco.Core/Persistence/Repositories/VersionableRepositoryBase.cs +++ b/src/Umbraco.Core/Persistence/Repositories/VersionableRepositoryBase.cs @@ -33,7 +33,7 @@ namespace Umbraco.Core.Persistence.Repositories { private readonly IContentSection _contentSection; - protected VersionableRepositoryBase(IDatabaseUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax, IContentSection contentSection) + protected VersionableRepositoryBase(IScopeUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax, IContentSection contentSection) : base(work, cache, logger, sqlSyntax) { _contentSection = contentSection; diff --git a/src/Umbraco.Core/Persistence/RepositoryFactory.cs b/src/Umbraco.Core/Persistence/RepositoryFactory.cs index e04c898015..620aa54546 100644 --- a/src/Umbraco.Core/Persistence/RepositoryFactory.cs +++ b/src/Umbraco.Core/Persistence/RepositoryFactory.cs @@ -88,42 +88,42 @@ namespace Umbraco.Core.Persistence #endregion - public virtual IExternalLoginRepository CreateExternalLoginRepository(IDatabaseUnitOfWork uow) + public virtual IExternalLoginRepository CreateExternalLoginRepository(IScopeUnitOfWork uow) { return new ExternalLoginRepository(uow, _cacheHelper, _logger, _sqlSyntax); } - public virtual IPublicAccessRepository CreatePublicAccessRepository(IDatabaseUnitOfWork uow) + public virtual IPublicAccessRepository CreatePublicAccessRepository(IScopeUnitOfWork uow) { return new PublicAccessRepository(uow, _cacheHelper, _logger, _sqlSyntax); } - public virtual ITaskRepository CreateTaskRepository(IDatabaseUnitOfWork uow) + public virtual ITaskRepository CreateTaskRepository(IScopeUnitOfWork uow) { return new TaskRepository(uow, _noCache, //never cache _logger, _sqlSyntax); } - public virtual IAuditRepository CreateAuditRepository(IDatabaseUnitOfWork uow) + public virtual IAuditRepository CreateAuditRepository(IScopeUnitOfWork uow) { return new AuditRepository(uow, _noCache, //never cache _logger, _sqlSyntax); } - public virtual ITagRepository CreateTagRepository(IDatabaseUnitOfWork uow) + public virtual ITagRepository CreateTagRepository(IScopeUnitOfWork uow) { return new TagRepository( uow, _cacheHelper, _logger, _sqlSyntax); } - public virtual IContentRepository CreateContentRepository(IDatabaseUnitOfWork uow) + public virtual IContentRepository CreateContentRepository(IScopeUnitOfWork uow) { return new ContentRepository( uow, @@ -139,7 +139,7 @@ namespace Umbraco.Core.Persistence }; } - public virtual IContentTypeRepository CreateContentTypeRepository(IDatabaseUnitOfWork uow) + public virtual IContentTypeRepository CreateContentTypeRepository(IScopeUnitOfWork uow) { return new ContentTypeRepository( uow, @@ -148,7 +148,7 @@ namespace Umbraco.Core.Persistence CreateTemplateRepository(uow)); } - public virtual IDataTypeDefinitionRepository CreateDataTypeDefinitionRepository(IDatabaseUnitOfWork uow) + public virtual IDataTypeDefinitionRepository CreateDataTypeDefinitionRepository(IScopeUnitOfWork uow) { return new DataTypeDefinitionRepository( uow, @@ -157,7 +157,7 @@ namespace Umbraco.Core.Persistence CreateContentTypeRepository(uow)); } - public virtual IDictionaryRepository CreateDictionaryRepository(IDatabaseUnitOfWork uow) + public virtual IDictionaryRepository CreateDictionaryRepository(IScopeUnitOfWork uow) { return new DictionaryRepository( uow, @@ -166,7 +166,7 @@ namespace Umbraco.Core.Persistence _sqlSyntax); } - public virtual ILanguageRepository CreateLanguageRepository(IDatabaseUnitOfWork uow) + public virtual ILanguageRepository CreateLanguageRepository(IScopeUnitOfWork uow) { return new LanguageRepository( uow, @@ -174,7 +174,7 @@ namespace Umbraco.Core.Persistence _logger, _sqlSyntax); } - public virtual IMediaRepository CreateMediaRepository(IDatabaseUnitOfWork uow) + public virtual IMediaRepository CreateMediaRepository(IScopeUnitOfWork uow) { return new MediaRepository( uow, @@ -185,7 +185,7 @@ namespace Umbraco.Core.Persistence _settings.Content); } - public virtual IMediaTypeRepository CreateMediaTypeRepository(IDatabaseUnitOfWork uow) + public virtual IMediaTypeRepository CreateMediaTypeRepository(IScopeUnitOfWork uow) { return new MediaTypeRepository( uow, @@ -193,7 +193,7 @@ namespace Umbraco.Core.Persistence _logger, _sqlSyntax); } - public virtual IRelationRepository CreateRelationRepository(IDatabaseUnitOfWork uow) + public virtual IRelationRepository CreateRelationRepository(IScopeUnitOfWork uow) { return new RelationRepository( uow, @@ -202,7 +202,7 @@ namespace Umbraco.Core.Persistence CreateRelationTypeRepository(uow)); } - public virtual IRelationTypeRepository CreateRelationTypeRepository(IDatabaseUnitOfWork uow) + public virtual IRelationTypeRepository CreateRelationTypeRepository(IScopeUnitOfWork uow) { return new RelationTypeRepository( uow, @@ -230,7 +230,7 @@ namespace Umbraco.Core.Persistence return new StylesheetRepository(uow, FileSystemProviderManager.Current.StylesheetsFileSystem); } - public virtual ITemplateRepository CreateTemplateRepository(IDatabaseUnitOfWork uow) + public virtual ITemplateRepository CreateTemplateRepository(IScopeUnitOfWork uow) { return new TemplateRepository(uow, _cacheHelper, @@ -245,7 +245,7 @@ namespace Umbraco.Core.Persistence return new XsltFileRepository(uow, FileSystemProviderManager.Current.XsltFileSystem); } - public virtual IMigrationEntryRepository CreateMigrationEntryRepository(IDatabaseUnitOfWork uow) + public virtual IMigrationEntryRepository CreateMigrationEntryRepository(IScopeUnitOfWork uow) { return new MigrationEntryRepository( uow, @@ -253,7 +253,7 @@ namespace Umbraco.Core.Persistence _logger, _sqlSyntax); } - public virtual IServerRegistrationRepository CreateServerRegistrationRepository(IDatabaseUnitOfWork uow) + public virtual IServerRegistrationRepository CreateServerRegistrationRepository(IScopeUnitOfWork uow) { return new ServerRegistrationRepository( uow, @@ -261,7 +261,7 @@ namespace Umbraco.Core.Persistence _logger, _sqlSyntax); } - public virtual IUserTypeRepository CreateUserTypeRepository(IDatabaseUnitOfWork uow) + public virtual IUserTypeRepository CreateUserTypeRepository(IScopeUnitOfWork uow) { return new UserTypeRepository( uow, @@ -270,7 +270,7 @@ namespace Umbraco.Core.Persistence _logger, _sqlSyntax); } - public virtual IUserRepository CreateUserRepository(IDatabaseUnitOfWork uow) + public virtual IUserRepository CreateUserRepository(IScopeUnitOfWork uow) { return new UserRepository( uow, @@ -280,14 +280,14 @@ namespace Umbraco.Core.Persistence CreateUserTypeRepository(uow)); } - internal virtual IMacroRepository CreateMacroRepository(IDatabaseUnitOfWork uow) + internal virtual IMacroRepository CreateMacroRepository(IScopeUnitOfWork uow) { return new MacroRepository(uow, _cacheHelper, _logger, _sqlSyntax); } - public virtual IMemberRepository CreateMemberRepository(IDatabaseUnitOfWork uow) + public virtual IMemberRepository CreateMemberRepository(IScopeUnitOfWork uow) { return new MemberRepository( uow, @@ -299,38 +299,38 @@ namespace Umbraco.Core.Persistence _settings.Content); } - public virtual IMemberTypeRepository CreateMemberTypeRepository(IDatabaseUnitOfWork uow) + public virtual IMemberTypeRepository CreateMemberTypeRepository(IScopeUnitOfWork uow) { return new MemberTypeRepository(uow, _cacheHelper, _logger, _sqlSyntax); } - public virtual IMemberGroupRepository CreateMemberGroupRepository(IDatabaseUnitOfWork uow) + public virtual IMemberGroupRepository CreateMemberGroupRepository(IScopeUnitOfWork uow) { return new MemberGroupRepository(uow, _cacheHelper, _logger, _sqlSyntax); } - public virtual IEntityRepository CreateEntityRepository(IDatabaseUnitOfWork uow) + public virtual IEntityRepository CreateEntityRepository(IScopeUnitOfWork uow) { return new EntityRepository(uow); } - public virtual IDomainRepository CreateDomainRepository(IDatabaseUnitOfWork uow) + public virtual IDomainRepository CreateDomainRepository(IScopeUnitOfWork uow) { return new DomainRepository(uow, _cacheHelper, _logger, _sqlSyntax); } - public ITaskTypeRepository CreateTaskTypeRepository(IDatabaseUnitOfWork uow) + public ITaskTypeRepository CreateTaskTypeRepository(IScopeUnitOfWork uow) { return new TaskTypeRepository(uow, _noCache, //never cache _logger, _sqlSyntax); } - internal virtual EntityContainerRepository CreateEntityContainerRepository(IDatabaseUnitOfWork uow, Guid containerObjectType) + internal virtual EntityContainerRepository CreateEntityContainerRepository(IScopeUnitOfWork uow, Guid containerObjectType) { return new EntityContainerRepository( uow, @@ -339,7 +339,7 @@ namespace Umbraco.Core.Persistence containerObjectType); } - public IRedirectUrlRepository CreateRedirectUrlRepository(IDatabaseUnitOfWork uow) + public IRedirectUrlRepository CreateRedirectUrlRepository(IScopeUnitOfWork uow) { return new RedirectUrlRepository( uow, @@ -348,7 +348,7 @@ namespace Umbraco.Core.Persistence _sqlSyntax); } - internal IStylesheetRepository CreateStylesheetRepository(IDatabaseUnitOfWork uow) + internal IStylesheetRepository CreateStylesheetRepository(IScopeUnitOfWork uow) { return new StylesheetRepository(uow, FileSystemProviderManager.Current.StylesheetsFileSystem); } diff --git a/src/Umbraco.Core/Persistence/UnitOfWork/IScopeUnitOfWork.cs b/src/Umbraco.Core/Persistence/UnitOfWork/IScopeUnitOfWork.cs index 6bc59da9ae..e5a76cc94e 100644 --- a/src/Umbraco.Core/Persistence/UnitOfWork/IScopeUnitOfWork.cs +++ b/src/Umbraco.Core/Persistence/UnitOfWork/IScopeUnitOfWork.cs @@ -2,7 +2,7 @@ using Umbraco.Core.Events; namespace Umbraco.Core.Persistence.UnitOfWork { - internal interface IScopeUnitOfWork : IDatabaseUnitOfWork + public interface IScopeUnitOfWork : IDatabaseUnitOfWork { IEventManager EventManager { get; } } diff --git a/src/Umbraco.Core/Persistence/UnitOfWork/IScopeUnitOfWorkProvider.cs b/src/Umbraco.Core/Persistence/UnitOfWork/IScopeUnitOfWorkProvider.cs index 6cedc56c33..b6f8335e1a 100644 --- a/src/Umbraco.Core/Persistence/UnitOfWork/IScopeUnitOfWorkProvider.cs +++ b/src/Umbraco.Core/Persistence/UnitOfWork/IScopeUnitOfWorkProvider.cs @@ -6,7 +6,7 @@ namespace Umbraco.Core.Persistence.UnitOfWork /// /// Defines a Unit of Work Provider for working with /// - internal interface IScopeUnitOfWorkProvider : IDatabaseUnitOfWorkProvider + public interface IScopeUnitOfWorkProvider : IDatabaseUnitOfWorkProvider { new IScopeUnitOfWork GetUnitOfWork(); IScopeUnitOfWork GetUnitOfWork(IsolationLevel isolationLevel); diff --git a/src/Umbraco.Core/Persistence/UnitOfWork/PetaPocoUnitOfWorkProvider.cs b/src/Umbraco.Core/Persistence/UnitOfWork/PetaPocoUnitOfWorkProvider.cs index 25f85a7ea2..ef311f9d49 100644 --- a/src/Umbraco.Core/Persistence/UnitOfWork/PetaPocoUnitOfWorkProvider.cs +++ b/src/Umbraco.Core/Persistence/UnitOfWork/PetaPocoUnitOfWorkProvider.cs @@ -57,6 +57,12 @@ namespace Umbraco.Core.Persistence.UnitOfWork } #region Implementation of IUnitOfWorkProvider + + //explicit implementation + IDatabaseUnitOfWork IDatabaseUnitOfWorkProvider.GetUnitOfWork() + { + return new PetaPocoUnitOfWork(_scopeProvider); + } /// /// Creates a Unit of work with a new UmbracoDatabase instance for the work item/transaction. @@ -67,13 +73,7 @@ namespace Umbraco.Core.Persistence.UnitOfWork /// the ApplicationContext.Current.DatabaseContext.Database. This is because each transaction should use it's own Database /// and we Dispose of this Database object when the UOW is disposed. /// - public IDatabaseUnitOfWork GetUnitOfWork() - { - return new PetaPocoUnitOfWork(_scopeProvider); - } - - //explicit implementation - IScopeUnitOfWork IScopeUnitOfWorkProvider.GetUnitOfWork() + public IScopeUnitOfWork GetUnitOfWork() { return new PetaPocoUnitOfWork(_scopeProvider); } @@ -85,16 +85,6 @@ namespace Umbraco.Core.Persistence.UnitOfWork } #endregion - - /// - /// Static helper method to return a new unit of work - /// - /// - internal static IDatabaseUnitOfWork CreateUnitOfWork(ILogger logger) - { - // fixme wtf? - var provider = new PetaPocoUnitOfWorkProvider(logger); - return provider.GetUnitOfWork(); - } + } } \ No newline at end of file diff --git a/src/Umbraco.Core/Services/PackagingService.cs b/src/Umbraco.Core/Services/PackagingService.cs index 4d8a2773ba..ca083391b4 100644 --- a/src/Umbraco.Core/Services/PackagingService.cs +++ b/src/Umbraco.Core/Services/PackagingService.cs @@ -40,7 +40,7 @@ namespace Umbraco.Core.Services private readonly ILocalizationService _localizationService; private readonly IEntityService _entityService; private readonly RepositoryFactory _repositoryFactory; - private readonly IDatabaseUnitOfWorkProvider _uowProvider; + private readonly IScopeUnitOfWorkProvider _uowProvider; private Dictionary _importedContentTypes; private IPackageInstallation _packageInstallation; private readonly IUserService _userService; @@ -58,7 +58,7 @@ namespace Umbraco.Core.Services IEntityService entityService, IUserService userService, RepositoryFactory repositoryFactory, - IDatabaseUnitOfWorkProvider uowProvider) + IScopeUnitOfWorkProvider uowProvider) { _logger = logger; _contentService = contentService; diff --git a/src/Umbraco.Core/Services/ServerRegistrationService.cs b/src/Umbraco.Core/Services/ServerRegistrationService.cs index 9e28f9a91c..fbd737fdf7 100644 --- a/src/Umbraco.Core/Services/ServerRegistrationService.cs +++ b/src/Umbraco.Core/Services/ServerRegistrationService.cs @@ -31,7 +31,7 @@ namespace Umbraco.Core.Services /// A repository factory. /// A logger. /// - public ServerRegistrationService(IDatabaseUnitOfWorkProvider uowProvider, RepositoryFactory repositoryFactory, ILogger logger, IEventMessagesFactory eventMessagesFactory) + public ServerRegistrationService(IScopeUnitOfWorkProvider uowProvider, RepositoryFactory repositoryFactory, ILogger logger, IEventMessagesFactory eventMessagesFactory) : base(uowProvider, repositoryFactory, logger, eventMessagesFactory) { _lrepo = new LockingRepository(UowProvider, diff --git a/src/Umbraco.Core/Services/ServiceContext.cs b/src/Umbraco.Core/Services/ServiceContext.cs index f2969de3be..48421e5345 100644 --- a/src/Umbraco.Core/Services/ServiceContext.cs +++ b/src/Umbraco.Core/Services/ServiceContext.cs @@ -161,7 +161,7 @@ namespace Umbraco.Core.Services /// public ServiceContext( RepositoryFactory repositoryFactory, - IDatabaseUnitOfWorkProvider dbUnitOfWorkProvider, + IScopeUnitOfWorkProvider dbUnitOfWorkProvider, IUnitOfWorkProvider fileUnitOfWorkProvider, BasePublishingStrategy publishingStrategy, CacheHelper cache, @@ -187,7 +187,7 @@ namespace Umbraco.Core.Services /// Builds the various services /// private void BuildServiceCache( - IDatabaseUnitOfWorkProvider dbUnitOfWorkProvider, + IScopeUnitOfWorkProvider dbUnitOfWorkProvider, IUnitOfWorkProvider fileUnitOfWorkProvider, BasePublishingStrategy publishingStrategy, CacheHelper cache, diff --git a/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs index 311ea52071..9f8dac1ecb 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs @@ -44,7 +44,7 @@ namespace Umbraco.Tests.Persistence.Repositories base.TearDown(); } - private ContentRepository CreateRepository(IDatabaseUnitOfWork unitOfWork, out ContentTypeRepository contentTypeRepository, out DataTypeDefinitionRepository dtdRepository) + private ContentRepository CreateRepository(IScopeUnitOfWork unitOfWork, out ContentTypeRepository contentTypeRepository, out DataTypeDefinitionRepository dtdRepository) { TemplateRepository tr; var ctRepository = CreateRepository(unitOfWork, out contentTypeRepository, out tr); @@ -52,13 +52,13 @@ namespace Umbraco.Tests.Persistence.Repositories return ctRepository; } - private ContentRepository CreateRepository(IDatabaseUnitOfWork unitOfWork, out ContentTypeRepository contentTypeRepository) + private ContentRepository CreateRepository(IScopeUnitOfWork unitOfWork, out ContentTypeRepository contentTypeRepository) { TemplateRepository tr; return CreateRepository(unitOfWork, out contentTypeRepository, out tr); } - private ContentRepository CreateRepository(IDatabaseUnitOfWork unitOfWork, out ContentTypeRepository contentTypeRepository, out TemplateRepository templateRepository) + private ContentRepository CreateRepository(IScopeUnitOfWork unitOfWork, out ContentTypeRepository contentTypeRepository, out TemplateRepository templateRepository) { templateRepository = new TemplateRepository(unitOfWork, CacheHelper, Logger, SqlSyntax, Mock.Of(), Mock.Of(), Mock.Of()); var tagRepository = new TagRepository(unitOfWork, CacheHelper, Logger, SqlSyntax); diff --git a/src/Umbraco.Tests/Persistence/Repositories/ContentTypeRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/ContentTypeRepositoryTest.cs index 84cdef73e1..ab75258cee 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/ContentTypeRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/ContentTypeRepositoryTest.cs @@ -40,7 +40,7 @@ namespace Umbraco.Tests.Persistence.Repositories base.TearDown(); } - private ContentRepository CreateRepository(IDatabaseUnitOfWork unitOfWork, out ContentTypeRepository contentTypeRepository) + private ContentRepository CreateRepository(IScopeUnitOfWork unitOfWork, out ContentTypeRepository contentTypeRepository) { var templateRepository = new TemplateRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntax, Mock.Of(), Mock.Of(), Mock.Of()); var tagRepository = new TagRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntax); @@ -49,20 +49,20 @@ namespace Umbraco.Tests.Persistence.Repositories return repository; } - private ContentTypeRepository CreateRepository(IDatabaseUnitOfWork unitOfWork) + private ContentTypeRepository CreateRepository(IScopeUnitOfWork unitOfWork) { var templateRepository = new TemplateRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntax, Mock.Of(), Mock.Of(), Mock.Of()); var contentTypeRepository = new ContentTypeRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntax, templateRepository); return contentTypeRepository; } - private MediaTypeRepository CreateMediaTypeRepository(IDatabaseUnitOfWork unitOfWork) + private MediaTypeRepository CreateMediaTypeRepository(IScopeUnitOfWork unitOfWork) { var contentTypeRepository = new MediaTypeRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntax); return contentTypeRepository; } - private EntityContainerRepository CreateContainerRepository(IDatabaseUnitOfWork unitOfWork, Guid containerEntityType) + private EntityContainerRepository CreateContainerRepository(IScopeUnitOfWork unitOfWork, Guid containerEntityType) { return new EntityContainerRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntax, containerEntityType); } diff --git a/src/Umbraco.Tests/Persistence/Repositories/DataTypeDefinitionRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/DataTypeDefinitionRepositoryTest.cs index 4db63f6085..b2f8ff9d73 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/DataTypeDefinitionRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/DataTypeDefinitionRepositoryTest.cs @@ -31,7 +31,7 @@ namespace Umbraco.Tests.Persistence.Repositories base.Initialize(); } - private DataTypeDefinitionRepository CreateRepository(IDatabaseUnitOfWork unitOfWork) + private DataTypeDefinitionRepository CreateRepository(IScopeUnitOfWork unitOfWork) { var dataTypeDefinitionRepository = new DataTypeDefinitionRepository( unitOfWork, CacheHelper.CreateDisabledCacheHelper(), @@ -41,7 +41,7 @@ namespace Umbraco.Tests.Persistence.Repositories return dataTypeDefinitionRepository; } - private EntityContainerRepository CreateContainerRepository(IDatabaseUnitOfWork unitOfWork) + private EntityContainerRepository CreateContainerRepository(IScopeUnitOfWork unitOfWork) { return new EntityContainerRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntax, Constants.ObjectTypes.DataTypeContainerGuid); } diff --git a/src/Umbraco.Tests/Persistence/Repositories/DictionaryRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/DictionaryRepositoryTest.cs index 6b56181eac..3a85978f40 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/DictionaryRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/DictionaryRepositoryTest.cs @@ -27,7 +27,7 @@ namespace Umbraco.Tests.Persistence.Repositories CreateTestData(); } - private DictionaryRepository CreateRepository(IDatabaseUnitOfWork unitOfWork) + private DictionaryRepository CreateRepository(IScopeUnitOfWork unitOfWork) { var dictionaryRepository = new DictionaryRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), new SqlCeSyntaxProvider()); return dictionaryRepository; diff --git a/src/Umbraco.Tests/Persistence/Repositories/DomainRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/DomainRepositoryTest.cs index 782eeaf4e9..f49caf65af 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/DomainRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/DomainRepositoryTest.cs @@ -20,7 +20,7 @@ namespace Umbraco.Tests.Persistence.Repositories [TestFixture] public class DomainRepositoryTest : BaseDatabaseFactoryTest { - private DomainRepository CreateRepository(IDatabaseUnitOfWork unitOfWork, out ContentTypeRepository contentTypeRepository, out ContentRepository contentRepository, out LanguageRepository languageRepository) + private DomainRepository CreateRepository(IScopeUnitOfWork unitOfWork, out ContentTypeRepository contentTypeRepository, out ContentRepository contentRepository, out LanguageRepository languageRepository) { var templateRepository = new TemplateRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Logger, SqlSyntax, Mock.Of(), Mock.Of(), Mock.Of()); var tagRepository = new TagRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Logger, SqlSyntax); diff --git a/src/Umbraco.Tests/Persistence/Repositories/LanguageRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/LanguageRepositoryTest.cs index e4c403b280..6dac497488 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/LanguageRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/LanguageRepositoryTest.cs @@ -26,7 +26,7 @@ namespace Umbraco.Tests.Persistence.Repositories CreateTestData(); } - private LanguageRepository CreateRepository(IDatabaseUnitOfWork unitOfWork) + private LanguageRepository CreateRepository(IScopeUnitOfWork unitOfWork) { return new LanguageRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntax); } diff --git a/src/Umbraco.Tests/Persistence/Repositories/LockedRepositoryTests.cs b/src/Umbraco.Tests/Persistence/Repositories/LockedRepositoryTests.cs index 7307be9d52..a17a648a08 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/LockedRepositoryTests.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/LockedRepositoryTests.cs @@ -19,7 +19,7 @@ namespace Umbraco.Tests.Persistence.Repositories [TestFixture] public class LockedRepositoryTests : BaseDatabaseFactoryTest { - private static IServerRegistrationRepository CreateRepository(IDatabaseUnitOfWork uow, ILogger logger, CacheHelper cacheHelper, ISqlSyntaxProvider sqlSyntax) + private static IServerRegistrationRepository CreateRepository(IScopeUnitOfWork uow, ILogger logger, CacheHelper cacheHelper, ISqlSyntaxProvider sqlSyntax) { return new ServerRegistrationRepository( uow, diff --git a/src/Umbraco.Tests/Persistence/Repositories/MediaRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/MediaRepositoryTest.cs index 1566441d5a..6883510a3f 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/MediaRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/MediaRepositoryTest.cs @@ -34,7 +34,7 @@ namespace Umbraco.Tests.Persistence.Repositories CreateTestData(); } - private MediaRepository CreateRepository(IDatabaseUnitOfWork unitOfWork, out MediaTypeRepository mediaTypeRepository) + private MediaRepository CreateRepository(IScopeUnitOfWork unitOfWork, out MediaTypeRepository mediaTypeRepository) { mediaTypeRepository = new MediaTypeRepository(unitOfWork, CacheHelper, Mock.Of(), SqlSyntax); var tagRepository = new TagRepository(unitOfWork, CacheHelper, Mock.Of(), SqlSyntax); diff --git a/src/Umbraco.Tests/Persistence/Repositories/MediaTypeRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/MediaTypeRepositoryTest.cs index b9ff045c71..ef039f4121 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/MediaTypeRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/MediaTypeRepositoryTest.cs @@ -26,12 +26,12 @@ namespace Umbraco.Tests.Persistence.Repositories base.Initialize(); } - private MediaTypeRepository CreateRepository(IDatabaseUnitOfWork unitOfWork) + private MediaTypeRepository CreateRepository(IScopeUnitOfWork unitOfWork) { return new MediaTypeRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntax); } - private EntityContainerRepository CreateContainerRepository(IDatabaseUnitOfWork unitOfWork) + private EntityContainerRepository CreateContainerRepository(IScopeUnitOfWork unitOfWork) { return new EntityContainerRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntax, Constants.ObjectTypes.MediaTypeContainerGuid); } diff --git a/src/Umbraco.Tests/Persistence/Repositories/MemberRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/MemberRepositoryTest.cs index e97fff03c8..befa2259ed 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/MemberRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/MemberRepositoryTest.cs @@ -35,7 +35,7 @@ namespace Umbraco.Tests.Persistence.Repositories base.TearDown(); } - private MemberRepository CreateRepository(IDatabaseUnitOfWork unitOfWork, out MemberTypeRepository memberTypeRepository, out MemberGroupRepository memberGroupRepository) + private MemberRepository CreateRepository(IScopeUnitOfWork unitOfWork, out MemberTypeRepository memberTypeRepository, out MemberGroupRepository memberGroupRepository) { memberTypeRepository = new MemberTypeRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntax); memberGroupRepository = new MemberGroupRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntax); diff --git a/src/Umbraco.Tests/Persistence/Repositories/MemberTypeRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/MemberTypeRepositoryTest.cs index 32341fac10..6b4f354703 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/MemberTypeRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/MemberTypeRepositoryTest.cs @@ -30,7 +30,7 @@ namespace Umbraco.Tests.Persistence.Repositories base.TearDown(); } - private MemberTypeRepository CreateRepository(IDatabaseUnitOfWork unitOfWork) + private MemberTypeRepository CreateRepository(IScopeUnitOfWork unitOfWork) { return new MemberTypeRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntax); } diff --git a/src/Umbraco.Tests/Persistence/Repositories/PublicAccessRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/PublicAccessRepositoryTest.cs index 4fa212f9bc..6d446e9174 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/PublicAccessRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/PublicAccessRepositoryTest.cs @@ -225,7 +225,7 @@ namespace Umbraco.Tests.Persistence.Repositories } - private ContentRepository CreateRepository(IDatabaseUnitOfWork unitOfWork, out ContentTypeRepository contentTypeRepository) + private ContentRepository CreateRepository(IScopeUnitOfWork unitOfWork, out ContentTypeRepository contentTypeRepository) { var templateRepository = new TemplateRepository(unitOfWork, CacheHelper, Logger, SqlSyntax, Mock.Of(), Mock.Of(), Mock.Of()); var tagRepository = new TagRepository(unitOfWork, CacheHelper, Logger, SqlSyntax); diff --git a/src/Umbraco.Tests/Persistence/Repositories/RedirectUrlRepositoryTests.cs b/src/Umbraco.Tests/Persistence/Repositories/RedirectUrlRepositoryTests.cs index 084d43d24c..d82004bb05 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/RedirectUrlRepositoryTests.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/RedirectUrlRepositoryTests.cs @@ -190,7 +190,7 @@ namespace Umbraco.Tests.Persistence.Repositories } } - private IRedirectUrlRepository CreateRepository(IDatabaseUnitOfWork uow) + private IRedirectUrlRepository CreateRepository(IScopeUnitOfWork uow) { return new RedirectUrlRepository(uow, CacheHelper.CreateDisabledCacheHelper(), Logger, SqlSyntax); } diff --git a/src/Umbraco.Tests/Persistence/Repositories/RelationRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/RelationRepositoryTest.cs index 82eec202ae..3639d03f2a 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/RelationRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/RelationRepositoryTest.cs @@ -30,7 +30,7 @@ namespace Umbraco.Tests.Persistence.Repositories CreateTestData(); } - private RelationRepository CreateRepository(IDatabaseUnitOfWork unitOfWork, out RelationTypeRepository relationTypeRepository) + private RelationRepository CreateRepository(IScopeUnitOfWork unitOfWork, out RelationTypeRepository relationTypeRepository) { relationTypeRepository = new RelationTypeRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntax); var repository = new RelationRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntax, relationTypeRepository); diff --git a/src/Umbraco.Tests/Persistence/Repositories/RelationTypeRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/RelationTypeRepositoryTest.cs index 2a95957ea8..9355b90546 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/RelationTypeRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/RelationTypeRepositoryTest.cs @@ -27,7 +27,7 @@ namespace Umbraco.Tests.Persistence.Repositories CreateTestData(); } - private RelationTypeRepository CreateRepository(IDatabaseUnitOfWork unitOfWork) + private RelationTypeRepository CreateRepository(IScopeUnitOfWork unitOfWork) { return new RelationTypeRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntax); } diff --git a/src/Umbraco.Tests/Persistence/Repositories/ServerRegistrationRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/ServerRegistrationRepositoryTest.cs index bcb49068fa..ef75fe2c99 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/ServerRegistrationRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/ServerRegistrationRepositoryTest.cs @@ -30,7 +30,7 @@ namespace Umbraco.Tests.Persistence.Repositories CreateTestData(); } - private ServerRegistrationRepository CreateRepository(IDatabaseUnitOfWork unitOfWork) + private ServerRegistrationRepository CreateRepository(IScopeUnitOfWork unitOfWork) { return new ServerRegistrationRepository(unitOfWork, _staticCache, Mock.Of(), SqlSyntax); } diff --git a/src/Umbraco.Tests/Persistence/Repositories/TagRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/TagRepositoryTest.cs index d79a45c2e9..fda7b26f4a 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/TagRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/TagRepositoryTest.cs @@ -33,7 +33,7 @@ namespace Umbraco.Tests.Persistence.Repositories base.TearDown(); } - private TagRepository CreateRepository(IDatabaseUnitOfWork unitOfWork) + private TagRepository CreateRepository(IScopeUnitOfWork unitOfWork) { var tagRepository = new TagRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntax); return tagRepository; @@ -1032,7 +1032,7 @@ namespace Umbraco.Tests.Persistence.Repositories } - private ContentRepository CreateContentRepository(IDatabaseUnitOfWork unitOfWork, out ContentTypeRepository contentTypeRepository) + private ContentRepository CreateContentRepository(IScopeUnitOfWork unitOfWork, out ContentTypeRepository contentTypeRepository) { var templateRepository = new TemplateRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntax, Mock.Of(), Mock.Of(), Mock.Of()); var tagRepository = new TagRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntax); @@ -1041,7 +1041,7 @@ namespace Umbraco.Tests.Persistence.Repositories return repository; } - private MediaRepository CreateMediaRepository(IDatabaseUnitOfWork unitOfWork, out MediaTypeRepository mediaTypeRepository) + private MediaRepository CreateMediaRepository(IScopeUnitOfWork unitOfWork, out MediaTypeRepository mediaTypeRepository) { var tagRepository = new TagRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntax); mediaTypeRepository = new MediaTypeRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntax); diff --git a/src/Umbraco.Tests/Persistence/Repositories/TemplateRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/TemplateRepositoryTest.cs index 1a4a7a2338..c8986d1036 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/TemplateRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/TemplateRepositoryTest.cs @@ -28,7 +28,7 @@ namespace Umbraco.Tests.Persistence.Repositories private IFileSystem _masterPageFileSystem; private IFileSystem _viewsFileSystem; - private ITemplateRepository CreateRepository(IDatabaseUnitOfWork unitOfWork, ITemplatesSection templatesSection = null) + private ITemplateRepository CreateRepository(IScopeUnitOfWork unitOfWork, ITemplatesSection templatesSection = null) { return new TemplateRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntax, _masterPageFileSystem, _viewsFileSystem, templatesSection ?? Mock.Of(t => t.DefaultRenderingEngine == RenderingEngine.Mvc)); diff --git a/src/Umbraco.Tests/Persistence/Repositories/UserRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/UserRepositoryTest.cs index 1d26e59113..0aae63d995 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/UserRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/UserRepositoryTest.cs @@ -32,7 +32,7 @@ namespace Umbraco.Tests.Persistence.Repositories base.TearDown(); } - private UserRepository CreateRepository(IDatabaseUnitOfWork unitOfWork, out UserTypeRepository userTypeRepository) + private UserRepository CreateRepository(IScopeUnitOfWork unitOfWork, out UserTypeRepository userTypeRepository) { userTypeRepository = new UserTypeRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntax); var repository = new UserRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntax, userTypeRepository); diff --git a/src/Umbraco.Tests/Persistence/Repositories/UserTypeRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/UserTypeRepositoryTest.cs index 5efc139931..963f9eb6aa 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/UserTypeRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/UserTypeRepositoryTest.cs @@ -30,7 +30,7 @@ namespace Umbraco.Tests.Persistence.Repositories base.TearDown(); } - private UserTypeRepository CreateRepository(IDatabaseUnitOfWork unitOfWork) + private UserTypeRepository CreateRepository(IScopeUnitOfWork unitOfWork) { return new UserTypeRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntax); } diff --git a/src/Umbraco.Tests/Services/ContentServiceTests.cs b/src/Umbraco.Tests/Services/ContentServiceTests.cs index 46af227ecd..b238a144f7 100644 --- a/src/Umbraco.Tests/Services/ContentServiceTests.cs +++ b/src/Umbraco.Tests/Services/ContentServiceTests.cs @@ -1469,7 +1469,8 @@ namespace Umbraco.Tests.Services [Test] public void Can_Save_Lazy_Content() { - var unitOfWork = PetaPocoUnitOfWorkProvider.CreateUnitOfWork(Mock.Of()); + var uowProvider = new PetaPocoUnitOfWorkProvider(Mock.Of()); + var unitOfWork = uowProvider.GetUnitOfWork(); var contentType = ServiceContext.ContentTypeService.GetContentType("umbTextpage"); var root = ServiceContext.ContentService.GetById(NodeDto.NodeIdSeed + 1); @@ -1743,7 +1744,7 @@ namespace Umbraco.Tests.Services return list; } - private ContentRepository CreateRepository(IDatabaseUnitOfWork unitOfWork, out ContentTypeRepository contentTypeRepository) + private ContentRepository CreateRepository(IScopeUnitOfWork unitOfWork, out ContentTypeRepository contentTypeRepository) { var templateRepository = new TemplateRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntax, Mock.Of(), Mock.Of(), Mock.Of()); var tagRepository = new TagRepository(unitOfWork, CacheHelper.CreateDisabledCacheHelper(), Mock.Of(), SqlSyntax); diff --git a/src/Umbraco.Tests/Templates/TemplateRepositoryTests.cs b/src/Umbraco.Tests/Templates/TemplateRepositoryTests.cs index c385799411..05c4059662 100644 --- a/src/Umbraco.Tests/Templates/TemplateRepositoryTests.cs +++ b/src/Umbraco.Tests/Templates/TemplateRepositoryTests.cs @@ -19,7 +19,7 @@ namespace Umbraco.Tests.Templates [TestFixture] public class TemplateRepositoryTests { - private readonly Mock _unitOfWorkMock = new Mock(); + private readonly Mock _unitOfWorkMock = new Mock(); private readonly Mock _cacheMock = new Mock(); private TemplateRepository _templateRepository; private readonly Mock _viewFileSystemMock = new Mock(); diff --git a/src/Umbraco.Tests/Web/Mvc/UmbracoViewPageTests.cs b/src/Umbraco.Tests/Web/Mvc/UmbracoViewPageTests.cs index 6d776b6d35..3ba6e06c7c 100644 --- a/src/Umbraco.Tests/Web/Mvc/UmbracoViewPageTests.cs +++ b/src/Umbraco.Tests/Web/Mvc/UmbracoViewPageTests.cs @@ -393,7 +393,7 @@ namespace Umbraco.Tests.Web.Mvc new Mock().Object, new Mock().Object, new RepositoryFactory(CacheHelper.CreateDisabledCacheHelper(), logger, Mock.Of(), umbracoSettings), - new Mock().Object), + new Mock().Object), new Mock().Object, new RelationService( new Mock().Object, From 8de8b53039b0b56fa310648aafb8490453fcb0a0 Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 19 Jan 2017 16:58:10 +1100 Subject: [PATCH 4/9] missing interface implementation --- .../UnitOfWork/PetaPocoUnitOfWork.cs | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/Umbraco.Core/Persistence/UnitOfWork/PetaPocoUnitOfWork.cs b/src/Umbraco.Core/Persistence/UnitOfWork/PetaPocoUnitOfWork.cs index ac677732c8..49ba09066f 100644 --- a/src/Umbraco.Core/Persistence/UnitOfWork/PetaPocoUnitOfWork.cs +++ b/src/Umbraco.Core/Persistence/UnitOfWork/PetaPocoUnitOfWork.cs @@ -156,12 +156,17 @@ namespace Umbraco.Core.Persistence.UnitOfWork get { return ThisScope.Database; } } - #region Operation + public IEventManager EventManager + { + get { return ThisScope.EventManager; } + } - /// - /// Provides a snapshot of an entity and the repository reference it belongs to. - /// - private sealed class Operation + #region Operation + + /// + /// Provides a snapshot of an entity and the repository reference it belongs to. + /// + private sealed class Operation { /// /// Gets or sets the entity. @@ -199,10 +204,6 @@ namespace Umbraco.Core.Persistence.UnitOfWork _scope.Dispose(); _scope = null; } - - public IEventManager EventManager - { - get { throw new NotImplementedException(); } - } + } } \ No newline at end of file From 9965aa461a9d4535f63e5b8e0b970acd508ff703 Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 19 Jan 2017 17:18:06 +1100 Subject: [PATCH 5/9] Updates ContentService to raise events all with the EventManager --- src/Umbraco.Core/Services/ContentService.cs | 264 +++++++++++--------- 1 file changed, 143 insertions(+), 121 deletions(-) diff --git a/src/Umbraco.Core/Services/ContentService.cs b/src/Umbraco.Core/Services/ContentService.cs index 5751bba542..343b4b66ad 100644 --- a/src/Umbraco.Core/Services/ContentService.cs +++ b/src/Umbraco.Core/Services/ContentService.cs @@ -164,8 +164,9 @@ namespace Umbraco.Core.Services var parent = GetById(content.ParentId); content.Path = string.Concat(parent.IfNotNull(x => x.Path, content.ParentId.ToString()), ",", content.Id); + var uow = UowProvider.GetUnitOfWork(); - if (Creating.IsRaisedEventCancelled(new NewEventArgs(content, contentTypeAlias, parentId), this)) + if (Creating.IsRaisedEventCancelled(new NewEventArgs(content, contentTypeAlias, parentId), this, uow.EventManager)) { content.WasCancelled = true; return content; @@ -174,9 +175,8 @@ namespace Umbraco.Core.Services content.CreatorId = userId; content.WriterId = userId; - Created.RaiseEvent(new NewEventArgs(content, false, contentTypeAlias, parentId), this); - - var uow = UowProvider.GetUnitOfWork(); + Created.RaiseEvent(new NewEventArgs(content, false, contentTypeAlias, parentId), this, uow.EventManager); + using (var auditRepo = RepositoryFactory.CreateAuditRepository(uow)) { auditRepo.AddOrUpdate(new AuditItem(content.Id, string.Format("Content '{0}' was created", name), AuditType.New, content.CreatorId)); @@ -208,20 +208,23 @@ namespace Umbraco.Core.Services var content = new Content(name, parent, contentType); content.Path = string.Concat(parent.Path, ",", content.Id); - if (Creating.IsRaisedEventCancelled(new NewEventArgs(content, contentTypeAlias, parent), this)) + using (var uow = UowProvider.GetUnitOfWork()) { - content.WasCancelled = true; + if (Creating.IsRaisedEventCancelled(new NewEventArgs(content, contentTypeAlias, parent), this, uow.EventManager)) + { + content.WasCancelled = true; + return content; + } + + content.CreatorId = userId; + content.WriterId = userId; + + Created.RaiseEvent(new NewEventArgs(content, false, contentTypeAlias, parent), this, uow.EventManager); + + Audit(AuditType.New, string.Format("Content '{0}' was created", name), content.CreatorId, content.Id); + return content; } - - content.CreatorId = userId; - content.WriterId = userId; - - Created.RaiseEvent(new NewEventArgs(content, false, contentTypeAlias, parent), this); - - Audit(AuditType.New, string.Format("Content '{0}' was created", name), content.CreatorId, content.Id); - - return content; } /// @@ -242,21 +245,22 @@ namespace Umbraco.Core.Services var contentType = FindContentTypeByAlias(contentTypeAlias); var content = new Content(name, parentId, contentType); + var uow = UowProvider.GetUnitOfWork(); + //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. - if (Creating.IsRaisedEventCancelled(new NewEventArgs(content, contentTypeAlias, parentId), this)) + if (Creating.IsRaisedEventCancelled(new NewEventArgs(content, contentTypeAlias, parentId), this, uow.EventManager)) { content.WasCancelled = true; return content; } - if (Saving.IsRaisedEventCancelled(new SaveEventArgs(content), this)) + if (Saving.IsRaisedEventCancelled(new SaveEventArgs(content), this, uow.EventManager)) { content.WasCancelled = true; return content; } - - var uow = UowProvider.GetUnitOfWork(); + using (var repository = RepositoryFactory.CreateContentRepository(uow)) { content.CreatorId = userId; @@ -265,12 +269,12 @@ namespace Umbraco.Core.Services //Generate a new preview repository.AddOrUpdatePreviewXml(content, c => _entitySerializer.Serialize(this, _dataTypeService, _userService, c)); uow.Commit(); + + Saved.RaiseEvent(new SaveEventArgs(content, false), this, uow.EventManager); + + Created.RaiseEvent(new NewEventArgs(content, false, contentTypeAlias, parentId), this, uow.EventManager); } - Saved.RaiseEvent(new SaveEventArgs(content, false), this); - - Created.RaiseEvent(new NewEventArgs(content, false, contentTypeAlias, parentId), this); - Audit(AuditType.New, string.Format("Content '{0}' was created with Id {1}", name, content.Id), content.CreatorId, content.Id); return content; @@ -296,21 +300,22 @@ namespace Umbraco.Core.Services var contentType = FindContentTypeByAlias(contentTypeAlias); var content = new Content(name, parent, contentType); + var uow = UowProvider.GetUnitOfWork(); + //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. - if (Creating.IsRaisedEventCancelled(new NewEventArgs(content, contentTypeAlias, parent), this)) + if (Creating.IsRaisedEventCancelled(new NewEventArgs(content, contentTypeAlias, parent), this, uow.EventManager)) { content.WasCancelled = true; return content; } - if (Saving.IsRaisedEventCancelled(new SaveEventArgs(content), this)) + if (Saving.IsRaisedEventCancelled(new SaveEventArgs(content), this, uow.EventManager)) { content.WasCancelled = true; return content; } - - var uow = UowProvider.GetUnitOfWork(); + using (var repository = RepositoryFactory.CreateContentRepository(uow)) { content.CreatorId = userId; @@ -319,12 +324,12 @@ namespace Umbraco.Core.Services //Generate a new preview repository.AddOrUpdatePreviewXml(content, c => _entitySerializer.Serialize(this, _dataTypeService, _userService, c)); uow.Commit(); + + Saved.RaiseEvent(new SaveEventArgs(content, false), this, uow.EventManager); + + Created.RaiseEvent(new NewEventArgs(content, false, contentTypeAlias, parent), this, uow.EventManager); } - Saved.RaiseEvent(new SaveEventArgs(content, false), this); - - Created.RaiseEvent(new NewEventArgs(content, false, contentTypeAlias, parent), this); - Audit(AuditType.New, string.Format("Content '{0}' was created with Id {1}", name, content.Id), content.CreatorId, content.Id); return content; @@ -1003,6 +1008,8 @@ namespace Umbraco.Core.Services using (new WriteLock(Locker)) { + var uow = UowProvider.GetUnitOfWork(); + //Hack: this ensures that the entity's path is valid and if not it fixes/persists it //see: http://issues.umbraco.org/issue/U4-9336 content.EnsureValidPath(Logger, entity => GetById(entity.ParentId), QuickUpdate); @@ -1011,7 +1018,7 @@ namespace Umbraco.Core.Services if (Trashing.IsRaisedEventCancelled( new MoveEventArgs(evtMsgs, new MoveEventInfo(content, originalPath, Constants.System.RecycleBinContent)), - this)) + this, uow.EventManager)) { return OperationStatus.Cancelled(evtMsgs); } @@ -1035,8 +1042,7 @@ namespace Umbraco.Core.Services //TODO: this shouldn't be a 'sub operation', and if it needs to be it cannot raise events and cannot be cancelled! UnPublish(descendant, userId); } - - var uow = UowProvider.GetUnitOfWork(); + using (var repository = RepositoryFactory.CreateContentRepository(uow)) { content.WriterId = userId; @@ -1056,7 +1062,7 @@ namespace Umbraco.Core.Services uow.Commit(); } - Trashed.RaiseEvent(new MoveEventArgs(false, evtMsgs, moveInfo.ToArray()), this); + Trashed.RaiseEvent(new MoveEventArgs(false, evtMsgs, moveInfo.ToArray()), this, uow.EventManager); Audit(AuditType.Move, "Move Content to Recycle Bin performed by user", userId, content.Id); @@ -1177,11 +1183,13 @@ namespace Umbraco.Core.Services var evtMsgs = EventMessagesFactory.Get(); + var uow = UowProvider.GetUnitOfWork(); + if (raiseEvents) { if (Saving.IsRaisedEventCancelled( new SaveEventArgs(asArray, evtMsgs), - this)) + this, uow.EventManager)) { return OperationStatus.Cancelled(evtMsgs); } @@ -1189,8 +1197,7 @@ namespace Umbraco.Core.Services using (new WriteLock(Locker)) { var containsNew = asArray.Any(x => x.HasIdentity == false); - - var uow = UowProvider.GetUnitOfWork(); + using (var repository = RepositoryFactory.CreateContentRepository(uow)) { if (containsNew) @@ -1223,7 +1230,7 @@ namespace Umbraco.Core.Services } if (raiseEvents) - Saved.RaiseEvent(new SaveEventArgs(asArray, false, evtMsgs), this); + Saved.RaiseEvent(new SaveEventArgs(asArray, false, evtMsgs), this, uow.EventManager); Audit(AuditType.Save, "Bulk Save content performed by user", userId == -1 ? 0 : userId, Constants.System.Root); @@ -1246,9 +1253,11 @@ namespace Umbraco.Core.Services using (new WriteLock(Locker)) { + var uow = UowProvider.GetUnitOfWork(); + if (Deleting.IsRaisedEventCancelled( new DeleteEventArgs(content, evtMsgs), - this)) + this, uow.EventManager)) { return OperationStatus.Cancelled(evtMsgs); } @@ -1265,15 +1274,14 @@ namespace Umbraco.Core.Services { Delete(child, userId); } - - var uow = UowProvider.GetUnitOfWork(); + using (var repository = RepositoryFactory.CreateContentRepository(uow)) { repository.Delete(content); uow.Commit(); var args = new DeleteEventArgs(content, false, evtMsgs); - Deleted.RaiseEvent(args, this); + Deleted.RaiseEvent(args, this, uow.EventManager); //remove any flagged media files repository.DeleteMediaFiles(args.MediaFilesToDelete); @@ -1346,7 +1354,7 @@ namespace Umbraco.Core.Services var query = Query.Builder.Where(x => x.ContentTypeId == contentTypeId); var contents = repository.GetByQuery(query).ToArray(); - if (Deleting.IsRaisedEventCancelled(new DeleteEventArgs(contents), this)) + if (Deleting.IsRaisedEventCancelled(new DeleteEventArgs(contents), this, uow.EventManager)) return; foreach (var content in contents.OrderByDescending(x => x.ParentId)) @@ -1396,17 +1404,18 @@ 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) { - if (DeletingVersions.IsRaisedEventCancelled(new DeleteRevisionsEventArgs(id, dateToRetain: versionDate), this)) - return; - var uow = UowProvider.GetUnitOfWork(); + + if (DeletingVersions.IsRaisedEventCancelled(new DeleteRevisionsEventArgs(id, dateToRetain: versionDate), this, uow.EventManager)) + return; + using (var repository = RepositoryFactory.CreateContentRepository(uow)) { repository.DeleteVersions(id, versionDate); uow.Commit(); } - DeletedVersions.RaiseEvent(new DeleteRevisionsEventArgs(id, false, dateToRetain: versionDate), this); + DeletedVersions.RaiseEvent(new DeleteRevisionsEventArgs(id, false, dateToRetain: versionDate), this, uow.EventManager); Audit(AuditType.Delete, "Delete Content by version date performed by user", userId, Constants.System.Root); } @@ -1423,7 +1432,9 @@ namespace Umbraco.Core.Services { using (new WriteLock(Locker)) { - if (DeletingVersions.IsRaisedEventCancelled(new DeleteRevisionsEventArgs(id, specificVersion: versionId), this)) + var uow = UowProvider.GetUnitOfWork(); + + if (DeletingVersions.IsRaisedEventCancelled(new DeleteRevisionsEventArgs(id, specificVersion: versionId), this, uow.EventManager)) return; if (deletePriorVersions) @@ -1431,15 +1442,14 @@ namespace Umbraco.Core.Services var content = GetByVersion(versionId); DeleteVersions(id, content.UpdateDate, userId); } - - var uow = UowProvider.GetUnitOfWork(); + using (var repository = RepositoryFactory.CreateContentRepository(uow)) { repository.DeleteVersion(versionId); uow.Commit(); } - DeletedVersions.RaiseEvent(new DeleteRevisionsEventArgs(id, false, specificVersion: versionId), this); + DeletedVersions.RaiseEvent(new DeleteRevisionsEventArgs(id, false, specificVersion: versionId), this, uow.EventManager); Audit(AuditType.Delete, "Delete Content by version performed by user", userId, Constants.System.Root); } @@ -1478,21 +1488,24 @@ namespace Umbraco.Core.Services return; } - if (Moving.IsRaisedEventCancelled( - new MoveEventArgs( - new MoveEventInfo(content, content.Path, parentId)), this)) + using (var uow = UowProvider.GetUnitOfWork()) { - return; + if (Moving.IsRaisedEventCancelled( + new MoveEventArgs( + new MoveEventInfo(content, content.Path, parentId)), this, uow.EventManager)) + { + return; + } + + //used to track all the moved entities to be given to the event + var moveInfo = new List>(); + + //call private method that does the recursive moving + PerformMove(content, parentId, userId, moveInfo); + + Moved.RaiseEvent(new MoveEventArgs(false, moveInfo.ToArray()), this, uow.EventManager); } - //used to track all the moved entities to be given to the event - var moveInfo = new List>(); - - //call private method that does the recursive moving - PerformMove(content, parentId, userId, moveInfo); - - Moved.RaiseEvent(new MoveEventArgs(false, moveInfo.ToArray()), this); - Audit(AuditType.Move, "Move Content performed by user", userId, content.Id); } } @@ -1509,7 +1522,8 @@ namespace Umbraco.Core.Services bool success; var nodeObjectType = new Guid(Constants.ObjectTypes.Document); - using (var repository = RepositoryFactory.CreateContentRepository(UowProvider.GetUnitOfWork())) + var uow = UowProvider.GetUnitOfWork(); + using (var repository = RepositoryFactory.CreateContentRepository(uow)) { //Create a dictionary of ids -> dictionary of property aliases + values entities = repository.GetEntitiesInRecycleBin() @@ -1519,12 +1533,12 @@ namespace Umbraco.Core.Services files = ((ContentRepository)repository).GetFilesInRecycleBinForUploadField(); - if (EmptyingRecycleBin.IsRaisedEventCancelled(new RecycleBinEventArgs(nodeObjectType, entities, files), this)) + if (EmptyingRecycleBin.IsRaisedEventCancelled(new RecycleBinEventArgs(nodeObjectType, entities, files), this, uow.EventManager)) return; success = repository.EmptyRecycleBin(); - EmptiedRecycleBin.RaiseEvent(new RecycleBinEventArgs(nodeObjectType, entities, files, success), this); + EmptiedRecycleBin.RaiseEvent(new RecycleBinEventArgs(nodeObjectType, entities, files, success), this, uow.EventManager); if (success) repository.DeleteMediaFiles(files); @@ -1570,10 +1584,11 @@ namespace Umbraco.Core.Services // A copy should never be set to published automatically even if the original was. copy.ChangePublishedState(PublishedState.Unpublished); - if (Copying.IsRaisedEventCancelled(new CopyEventArgs(content, copy, parentId), this)) - return null; - var uow = UowProvider.GetUnitOfWork(); + + if (Copying.IsRaisedEventCancelled(new CopyEventArgs(content, copy, parentId), this, uow.EventManager)) + return null; + using (var repository = RepositoryFactory.CreateContentRepository(uow)) { // Update the create author and last edit author @@ -1612,7 +1627,7 @@ namespace Umbraco.Core.Services } } - Copied.RaiseEvent(new CopyEventArgs(content, copy, false, parentId, relateToOriginal), this); + Copied.RaiseEvent(new CopyEventArgs(content, copy, false, parentId, relateToOriginal), this, uow.EventManager); Audit(AuditType.Copy, "Copy Content performed by user", content.WriterId, content.Id); return copy; @@ -1628,17 +1643,20 @@ namespace Umbraco.Core.Services /// True if sending publication was succesfull otherwise false public bool SendToPublication(IContent content, int userId = 0) { - if (SendingToPublish.IsRaisedEventCancelled(new SendToPublishEventArgs(content), this)) - return false; + using (var uow = UowProvider.GetUnitOfWork()) + { + if (SendingToPublish.IsRaisedEventCancelled(new SendToPublishEventArgs(content), this, uow.EventManager)) + return false; - //Save before raising event - Save(content, userId); + //Save before raising event + Save(content, userId); - SentToPublish.RaiseEvent(new SendToPublishEventArgs(content, false), this); + SentToPublish.RaiseEvent(new SendToPublishEventArgs(content, false), this, uow.EventManager); - Audit(AuditType.SendToPublish, "Send to Publish performed by user", content.WriterId, content.Id); + Audit(AuditType.SendToPublish, "Send to Publish performed by user", content.WriterId, content.Id); - return true; + return true; + } } /// @@ -1657,10 +1675,11 @@ namespace Umbraco.Core.Services { var content = GetByVersion(versionId); - if (RollingBack.IsRaisedEventCancelled(new RollbackEventArgs(content), this)) - return content; - var uow = UowProvider.GetUnitOfWork(); + + if (RollingBack.IsRaisedEventCancelled(new RollbackEventArgs(content), this, uow.EventManager)) + return content; + using (var repository = RepositoryFactory.CreateContentRepository(uow)) { content.WriterId = userId; @@ -1673,7 +1692,7 @@ namespace Umbraco.Core.Services uow.Commit(); } - RolledBack.RaiseEvent(new RollbackEventArgs(content, false), this); + RolledBack.RaiseEvent(new RollbackEventArgs(content, false), this, uow.EventManager); Audit(AuditType.RollBack, "Content rollback performed by user", content.WriterId, content.Id); @@ -1694,19 +1713,20 @@ namespace Umbraco.Core.Services /// True if sorting succeeded, otherwise False public bool Sort(IEnumerable items, int userId = 0, bool raiseEvents = true) { - var asArray = items.ToArray(); - if (raiseEvents) - { - if (Saving.IsRaisedEventCancelled(new SaveEventArgs(asArray), this)) - return false; - } - var shouldBePublished = new List(); var shouldBeSaved = new List(); using (new WriteLock(Locker)) { var uow = UowProvider.GetUnitOfWork(); + + var asArray = items.ToArray(); + if (raiseEvents) + { + if (Saving.IsRaisedEventCancelled(new SaveEventArgs(asArray), this, uow.EventManager)) + return false; + } + using (var repository = RepositoryFactory.CreateContentRepository(uow)) { int i = 0; @@ -1747,15 +1767,15 @@ namespace Umbraco.Core.Services uow.Commit(); } - } - if (raiseEvents) - Saved.RaiseEvent(new SaveEventArgs(asArray, false), this); + if (raiseEvents) + Saved.RaiseEvent(new SaveEventArgs(asArray, false), this, uow.EventManager); - if (shouldBePublished.Any()) - { - //TODO: This should not be an inner operation, but if we do this, it cannot raise events and cannot be cancellable! - _publishingStrategy.PublishingFinalized(shouldBePublished, false); + if (shouldBePublished.Any()) + { + //TODO: This should not be an inner operation, but if we do this, it cannot raise events and cannot be cancellable! + _publishingStrategy.PublishingFinalized(shouldBePublished, false); + } } @@ -2080,19 +2100,21 @@ namespace Umbraco.Core.Services /// True if publishing succeeded, otherwise False private Attempt SaveAndPublishDo(IContent content, int userId = 0, bool raiseEvents = true) { - var evtMsgs = EventMessagesFactory.Get(); - - if (raiseEvents) - { - if (Saving.IsRaisedEventCancelled( - new SaveEventArgs(content, evtMsgs), this)) - { - return Attempt.Fail(new PublishStatus(content, PublishStatusType.FailedCancelledByEvent, evtMsgs)); - } - } + var evtMsgs = EventMessagesFactory.Get(); using (new WriteLock(Locker)) { + var uow = UowProvider.GetUnitOfWork(); + + if (raiseEvents) + { + if (Saving.IsRaisedEventCancelled( + new SaveEventArgs(content, evtMsgs), this, uow.EventManager)) + { + return Attempt.Fail(new PublishStatus(content, PublishStatusType.FailedCancelledByEvent, evtMsgs)); + } + } + //Has this content item previously been published? If so, we don't need to refresh the children var previouslyPublished = content.HasIdentity && HasPublishedVersion(content.Id); //content might not have an id var publishStatus = new PublishStatus(content, PublishStatusType.Success, evtMsgs); //initially set to success @@ -2119,8 +2141,7 @@ namespace Umbraco.Core.Services //we are successfully published if our publishStatus is still Successful bool published = publishStatus.StatusType == PublishStatusType.Success; - - var uow = UowProvider.GetUnitOfWork(); + using (var repository = RepositoryFactory.CreateContentRepository(uow)) { if (published == false) @@ -2149,7 +2170,7 @@ namespace Umbraco.Core.Services } if (raiseEvents) - Saved.RaiseEvent(new SaveEventArgs(content, false, evtMsgs), this); + Saved.RaiseEvent(new SaveEventArgs(content, false, evtMsgs), this, uow.EventManager); //Save xml to db and call following method to fire event through PublishingStrategy to update cache if (published) @@ -2181,20 +2202,21 @@ namespace Umbraco.Core.Services private Attempt Save(IContent content, bool changeState, int userId = 0, bool raiseEvents = true) { var evtMsgs = EventMessagesFactory.Get(); - - if (raiseEvents) - { - if (Saving.IsRaisedEventCancelled( - new SaveEventArgs(content, evtMsgs), - this)) - { - return OperationStatus.Cancelled(evtMsgs); - } - } - + using (new WriteLock(Locker)) { var uow = UowProvider.GetUnitOfWork(); + + if (raiseEvents) + { + if (Saving.IsRaisedEventCancelled( + new SaveEventArgs(content, evtMsgs), + this, uow.EventManager)) + { + return OperationStatus.Cancelled(evtMsgs); + } + } + using (var repository = RepositoryFactory.CreateContentRepository(uow)) { if (content.HasIdentity == false) @@ -2216,7 +2238,7 @@ namespace Umbraco.Core.Services } if (raiseEvents) - Saved.RaiseEvent(new SaveEventArgs(content, false, evtMsgs), this); + Saved.RaiseEvent(new SaveEventArgs(content, false, evtMsgs), this, uow.EventManager); Audit(AuditType.Save, "Save Content performed by user", userId, content.Id); From 2a95ed3c7a4473aa707dab4cc3bee6741a237935 Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 19 Jan 2017 17:29:36 +1100 Subject: [PATCH 6/9] no need for explicit implementation for this since we changed the old one --- .../Persistence/UnitOfWork/PetaPocoUnitOfWorkProvider.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Core/Persistence/UnitOfWork/PetaPocoUnitOfWorkProvider.cs b/src/Umbraco.Core/Persistence/UnitOfWork/PetaPocoUnitOfWorkProvider.cs index ef311f9d49..e06d522499 100644 --- a/src/Umbraco.Core/Persistence/UnitOfWork/PetaPocoUnitOfWorkProvider.cs +++ b/src/Umbraco.Core/Persistence/UnitOfWork/PetaPocoUnitOfWorkProvider.cs @@ -79,7 +79,7 @@ namespace Umbraco.Core.Persistence.UnitOfWork } //explicit implementation - IScopeUnitOfWork IScopeUnitOfWorkProvider.GetUnitOfWork(IsolationLevel isolationLevel) + public IScopeUnitOfWork GetUnitOfWork(IsolationLevel isolationLevel) { return new PetaPocoUnitOfWork(_scopeProvider, isolationLevel); } From a275567dbaf00eb454623f42dbfd3f8ee7e3b612 Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 19 Jan 2017 17:34:15 +1100 Subject: [PATCH 7/9] Adds equality members to the EventDefinitionBase so they are tracked by their unique id, makes IEventManager disposable and disposes it on scope end. --- .../Events/EventDefinitionBase.cs | 32 ++++++++++++++++++- src/Umbraco.Core/Events/IEventManager.cs | 2 +- .../Events/NoScopedEventManager.cs | 10 +++++- src/Umbraco.Core/Events/ScopedEventManager.cs | 10 +++++- .../UnitOfWork/PetaPocoUnitOfWorkProvider.cs | 10 +++++- src/Umbraco.Core/Scoping/Scope.cs | 5 +++ 6 files changed, 64 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Core/Events/EventDefinitionBase.cs b/src/Umbraco.Core/Events/EventDefinitionBase.cs index 4e33a6f6e6..754ed2fce5 100644 --- a/src/Umbraco.Core/Events/EventDefinitionBase.cs +++ b/src/Umbraco.Core/Events/EventDefinitionBase.cs @@ -2,7 +2,7 @@ using System; namespace Umbraco.Core.Events { - public abstract class EventDefinitionBase : IEventDefinition + public abstract class EventDefinitionBase : IEventDefinition, IEquatable { protected EventDefinitionBase() { @@ -10,5 +10,35 @@ namespace Umbraco.Core.Events } public Guid EventId { get; private set; } public abstract void RaiseEvent(); + + public bool Equals(EventDefinitionBase other) + { + if (ReferenceEquals(null, other)) return false; + if (ReferenceEquals(this, other)) return true; + return EventId.Equals(other.EventId); + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + if (obj.GetType() != this.GetType()) return false; + return Equals((EventDefinitionBase) obj); + } + + public override int GetHashCode() + { + return EventId.GetHashCode(); + } + + public static bool operator ==(EventDefinitionBase left, EventDefinitionBase right) + { + return Equals(left, right); + } + + public static bool operator !=(EventDefinitionBase left, EventDefinitionBase right) + { + return Equals(left, right) == false; + } } } \ No newline at end of file diff --git a/src/Umbraco.Core/Events/IEventManager.cs b/src/Umbraco.Core/Events/IEventManager.cs index 21339f07b1..d22d31f930 100644 --- a/src/Umbraco.Core/Events/IEventManager.cs +++ b/src/Umbraco.Core/Events/IEventManager.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; namespace Umbraco.Core.Events { - public interface IEventManager + public interface IEventManager : IDisposable { IEnumerable GetEvents(); void TrackEvent(EventHandler e, object sender, EventArgs args); diff --git a/src/Umbraco.Core/Events/NoScopedEventManager.cs b/src/Umbraco.Core/Events/NoScopedEventManager.cs index 35f964bf0a..27bb68f8e6 100644 --- a/src/Umbraco.Core/Events/NoScopedEventManager.cs +++ b/src/Umbraco.Core/Events/NoScopedEventManager.cs @@ -4,7 +4,10 @@ using System.Linq; namespace Umbraco.Core.Events { - internal class NoScopedEventManager : IEventManager + /// + /// This event manager supports event cancellation and will raise the events as soon as they are tracked, it does not store tracked events + /// + internal class NoScopedEventManager : DisposableObject, IEventManager { public void TrackEvent(EventHandler e, object sender, EventArgs args) { @@ -30,5 +33,10 @@ namespace Umbraco.Core.Events { get { return true; } } + + protected override void DisposeResources() + { + //noop + } } } \ No newline at end of file diff --git a/src/Umbraco.Core/Events/ScopedEventManager.cs b/src/Umbraco.Core/Events/ScopedEventManager.cs index 01e2d5e23f..354858cdb1 100644 --- a/src/Umbraco.Core/Events/ScopedEventManager.cs +++ b/src/Umbraco.Core/Events/ScopedEventManager.cs @@ -3,7 +3,10 @@ using System.Collections.Generic; namespace Umbraco.Core.Events { - internal class ScopedEventManager : IEventManager + /// + /// This event manager does not support event cancellation and will track all raised events in a list which can be retrieved + /// + internal class ScopedEventManager : DisposableObject, IEventManager { public void TrackEvent(EventHandler e, object sender, EventArgs args) { @@ -31,5 +34,10 @@ namespace Umbraco.Core.Events { get { return false; } } + + protected override void DisposeResources() + { + _tracked.Clear(); + } } } \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/UnitOfWork/PetaPocoUnitOfWorkProvider.cs b/src/Umbraco.Core/Persistence/UnitOfWork/PetaPocoUnitOfWorkProvider.cs index e06d522499..7bcfcba2b9 100644 --- a/src/Umbraco.Core/Persistence/UnitOfWork/PetaPocoUnitOfWorkProvider.cs +++ b/src/Umbraco.Core/Persistence/UnitOfWork/PetaPocoUnitOfWorkProvider.cs @@ -78,7 +78,15 @@ namespace Umbraco.Core.Persistence.UnitOfWork return new PetaPocoUnitOfWork(_scopeProvider); } - //explicit implementation + /// + /// Creates a Unit of work with a new UmbracoDatabase instance for the work item/transaction. + /// + /// + /// + /// Each PetaPoco UOW uses it's own Database object, not the shared Database object that comes from + /// the ApplicationContext.Current.DatabaseContext.Database. This is because each transaction should use it's own Database + /// and we Dispose of this Database object when the UOW is disposed. + /// public IScopeUnitOfWork GetUnitOfWork(IsolationLevel isolationLevel) { return new PetaPocoUnitOfWork(_scopeProvider, isolationLevel); diff --git a/src/Umbraco.Core/Scoping/Scope.cs b/src/Umbraco.Core/Scoping/Scope.cs index ba0092b9cb..a5f026412a 100644 --- a/src/Umbraco.Core/Scoping/Scope.cs +++ b/src/Umbraco.Core/Scoping/Scope.cs @@ -208,6 +208,11 @@ namespace Umbraco.Core.Scoping else DisposeLastScope(); + if (_eventManager != null) + { + _eventManager.Dispose(); + } + _disposed = true; GC.SuppressFinalize(this); } From b51e571803d652bbc06eb1e618bca482f809bd04 Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 19 Jan 2017 18:25:45 +1100 Subject: [PATCH 8/9] Adds unit tests and fixes others --- .../Services/RepositoryService.cs | 13 --- .../Services/ScopeRepositoryService.cs | 21 +++++ src/Umbraco.Core/Umbraco.Core.csproj | 1 + .../Scoping/NoScopedEventManagerTests.cs | 67 ++++++++++++++ src/Umbraco.Tests/Scoping/ScopeTests.cs | 1 + .../Scoping/ScopedEventManagerTests.cs | 90 +++++++++++++++++++ src/Umbraco.Tests/Umbraco.Tests.csproj | 2 + .../Web/Mvc/UmbracoViewPageTests.cs | 2 +- 8 files changed, 183 insertions(+), 14 deletions(-) create mode 100644 src/Umbraco.Core/Services/ScopeRepositoryService.cs create mode 100644 src/Umbraco.Tests/Scoping/NoScopedEventManagerTests.cs create mode 100644 src/Umbraco.Tests/Scoping/ScopedEventManagerTests.cs diff --git a/src/Umbraco.Core/Services/RepositoryService.cs b/src/Umbraco.Core/Services/RepositoryService.cs index b1e0cf7d21..88807f0291 100644 --- a/src/Umbraco.Core/Services/RepositoryService.cs +++ b/src/Umbraco.Core/Services/RepositoryService.cs @@ -6,19 +6,6 @@ using Umbraco.Core.Persistence.UnitOfWork; namespace Umbraco.Core.Services { - public abstract class ScopeRepositoryService : RepositoryService - { - protected ScopeRepositoryService(IDatabaseUnitOfWorkProvider provider, RepositoryFactory repositoryFactory, ILogger logger, IEventMessagesFactory eventMessagesFactory) - : base(provider, repositoryFactory, logger, eventMessagesFactory) - { - var scopeUow = provider as IScopeUnitOfWorkProvider; - if (scopeUow == null) throw new NotSupportedException("The provider type passed in: " + provider.GetType() + " is not of type " + typeof(IScopeUnitOfWorkProvider)); - UowProvider = scopeUow; - } - - internal new IScopeUnitOfWorkProvider UowProvider { get; private set; } - } - /// /// Base service class /// diff --git a/src/Umbraco.Core/Services/ScopeRepositoryService.cs b/src/Umbraco.Core/Services/ScopeRepositoryService.cs new file mode 100644 index 0000000000..0942aefd6f --- /dev/null +++ b/src/Umbraco.Core/Services/ScopeRepositoryService.cs @@ -0,0 +1,21 @@ +using System; +using Umbraco.Core.Events; +using Umbraco.Core.Logging; +using Umbraco.Core.Persistence; +using Umbraco.Core.Persistence.UnitOfWork; + +namespace Umbraco.Core.Services +{ + public abstract class ScopeRepositoryService : RepositoryService + { + protected ScopeRepositoryService(IDatabaseUnitOfWorkProvider provider, RepositoryFactory repositoryFactory, ILogger logger, IEventMessagesFactory eventMessagesFactory) + : base(provider, repositoryFactory, logger, eventMessagesFactory) + { + var scopeUow = provider as IScopeUnitOfWorkProvider; + if (scopeUow == null) throw new NotSupportedException("The provider type passed in: " + provider.GetType() + " is not of type " + typeof(IScopeUnitOfWorkProvider)); + UowProvider = scopeUow; + } + + internal new IScopeUnitOfWorkProvider UowProvider { get; private set; } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index cb4a157d18..88555db603 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -574,6 +574,7 @@ + diff --git a/src/Umbraco.Tests/Scoping/NoScopedEventManagerTests.cs b/src/Umbraco.Tests/Scoping/NoScopedEventManagerTests.cs new file mode 100644 index 0000000000..6975b578ab --- /dev/null +++ b/src/Umbraco.Tests/Scoping/NoScopedEventManagerTests.cs @@ -0,0 +1,67 @@ +using System; +using System.Linq; +using Moq; +using NUnit.Framework; +using Umbraco.Core.Events; +using Umbraco.Core.Persistence; +using Umbraco.Core.Persistence.UnitOfWork; +using Umbraco.Core.Scoping; + +namespace Umbraco.Tests.Scoping +{ + [TestFixture] + public class NoScopedEventManagerTests + { + + [Test] + public void Does_Support_Event_Cancellation() + { + var scopeProvider = new ScopeProvider(Mock.Of()); + Assert.IsTrue(scopeProvider.AmbientOrNoScope.EventManager.SupportsEventCancellation); + } + + [Test] + public void Does_Immediately_Raise_Events() + { + var counter = 0; + + this.DoThing1 += (sender, args) => + { + counter++; + }; + + this.DoThing2 += (sender, args) => + { + counter++; + }; + + this.DoThing3 += (sender, args) => + { + counter++; + }; + + var scopeProvider = new ScopeProvider(Mock.Of()); + scopeProvider.AmbientOrNoScope.EventManager.TrackEvent(DoThing1, this, new EventArgs()); + scopeProvider.AmbientOrNoScope.EventManager.TrackEvent(DoThing2, this, new EventArgs()); + scopeProvider.AmbientOrNoScope.EventManager.TrackEvent(DoThing3, this, new EventArgs()); + + Assert.AreEqual(3, counter); + + } + + [Test] + public void Can_Not_Raise_Events_Later() + { + var scopeProvider = new ScopeProvider(Mock.Of()); + scopeProvider.AmbientOrNoScope.EventManager.TrackEvent(DoThing1, this, new EventArgs()); + scopeProvider.AmbientOrNoScope.EventManager.TrackEvent(DoThing2, this, new EventArgs()); + scopeProvider.AmbientOrNoScope.EventManager.TrackEvent(DoThing3, this, new EventArgs()); + + Assert.AreEqual(0, scopeProvider.AmbientOrNoScope.EventManager.GetEvents().Count()); + } + + public event EventHandler DoThing1; + public event EventHandler DoThing2; + public event TypedEventHandler DoThing3; + } +} \ No newline at end of file diff --git a/src/Umbraco.Tests/Scoping/ScopeTests.cs b/src/Umbraco.Tests/Scoping/ScopeTests.cs index f6a9ab71df..c8ec425bca 100644 --- a/src/Umbraco.Tests/Scoping/ScopeTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopeTests.cs @@ -4,6 +4,7 @@ using Umbraco.Core; using Umbraco.Core.Persistence; using Umbraco.Core.Scoping; using Umbraco.Tests.TestHelpers; +using Umbraco.Core.Events; namespace Umbraco.Tests.Scoping { diff --git a/src/Umbraco.Tests/Scoping/ScopedEventManagerTests.cs b/src/Umbraco.Tests/Scoping/ScopedEventManagerTests.cs new file mode 100644 index 0000000000..3ddd0f7e08 --- /dev/null +++ b/src/Umbraco.Tests/Scoping/ScopedEventManagerTests.cs @@ -0,0 +1,90 @@ +using System; +using Moq; +using NUnit.Framework; +using Umbraco.Core.Events; +using Umbraco.Core.Persistence; +using Umbraco.Core.Persistence.UnitOfWork; +using Umbraco.Core.Scoping; + +namespace Umbraco.Tests.Scoping +{ + [TestFixture] + public class ScopedEventManagerTests + { + + [Test] + public void Does_Not_Support_Event_Cancellation() + { + var provider = new PetaPocoUnitOfWorkProvider(new ScopeProvider(Mock.Of())); + using (var uow = provider.GetUnitOfWork()) + { + Assert.IsFalse(uow.EventManager.SupportsEventCancellation); + } + } + + [Test] + public void Does_Not_Immediately_Raise_Events() + { + this.DoThing1 += OnDoThingFail; + this.DoThing2 += OnDoThingFail; + this.DoThing3 += OnDoThingFail; + + var provider = new PetaPocoUnitOfWorkProvider(new ScopeProvider(Mock.Of())); + using (var uow = provider.GetUnitOfWork()) + { + uow.EventManager.TrackEvent(DoThing1, this, new EventArgs()); + uow.EventManager.TrackEvent(DoThing2, this, new EventArgs()); + uow.EventManager.TrackEvent(DoThing3, this, new EventArgs()); + + Assert.Pass(); + } + } + + [Test] + public void Can_Raise_Events_Later() + { + var counter = 0; + + this.DoThing1 += (sender, args) => + { + counter++; + }; + + this.DoThing2 += (sender, args) => + { + counter++; + }; + + this.DoThing3 += (sender, args) => + { + counter++; + }; + + var provider = new PetaPocoUnitOfWorkProvider(new ScopeProvider(Mock.Of())); + using (var uow = provider.GetUnitOfWork()) + { + uow.EventManager.TrackEvent(DoThing1, this, new EventArgs()); + uow.EventManager.TrackEvent(DoThing2, this, new EventArgs()); + uow.EventManager.TrackEvent(DoThing3, this, new EventArgs()); + + Assert.AreEqual(0, counter); + + foreach (var e in uow.EventManager.GetEvents()) + { + e.RaiseEvent(); + } + + Assert.AreEqual(3, counter); + } + } + + private void OnDoThingFail(object sender, EventArgs eventArgs) + { + Assert.Fail(); + } + + public event EventHandler DoThing1; + public event EventHandler DoThing2; + public event TypedEventHandler DoThing3; + } +} \ No newline at end of file diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj index bdfcac3420..45cfc6cfd7 100644 --- a/src/Umbraco.Tests/Umbraco.Tests.csproj +++ b/src/Umbraco.Tests/Umbraco.Tests.csproj @@ -170,6 +170,8 @@ + + diff --git a/src/Umbraco.Tests/Web/Mvc/UmbracoViewPageTests.cs b/src/Umbraco.Tests/Web/Mvc/UmbracoViewPageTests.cs index 3ba6e06c7c..f83b8a6369 100644 --- a/src/Umbraco.Tests/Web/Mvc/UmbracoViewPageTests.cs +++ b/src/Umbraco.Tests/Web/Mvc/UmbracoViewPageTests.cs @@ -396,7 +396,7 @@ namespace Umbraco.Tests.Web.Mvc new Mock().Object), new Mock().Object, new RelationService( - new Mock().Object, + new Mock().Object, new RepositoryFactory(CacheHelper.CreateDisabledCacheHelper(), logger, Mock.Of(), umbracoSettings), logger, new TransientMessagesFactory(), From a6996922b7d276265e2e50da8626b8f9e5568fc3 Mon Sep 17 00:00:00 2001 From: Shannon Date: Fri, 20 Jan 2017 17:45:46 +1100 Subject: [PATCH 9/9] Adds more support for auto-finding event names, adds tests to support with examples of how to interrogate queued events --- src/Umbraco.Core/Events/EventDefinition.cs | 3 + .../Events/EventDefinitionBase.cs | 35 +++- src/Umbraco.Core/Events/EventNameExtractor.cs | 150 ++++++++++++++++++ .../Events/EventNameExtractorError.cs | 9 ++ .../Events/EventNameExtractorResult.cs | 18 +++ src/Umbraco.Core/Events/IEventDefinition.cs | 4 +- src/Umbraco.Core/Events/ScopedEventManager.cs | 2 + src/Umbraco.Core/Umbraco.Core.csproj | 3 + .../Scoping/EventNameExtractorTests.cs | 51 ++++++ .../Scoping/ScopedEventManagerTests.cs | 78 +++++++-- src/Umbraco.Tests/Umbraco.Tests.csproj | 1 + 11 files changed, 331 insertions(+), 23 deletions(-) create mode 100644 src/Umbraco.Core/Events/EventNameExtractor.cs create mode 100644 src/Umbraco.Core/Events/EventNameExtractorError.cs create mode 100644 src/Umbraco.Core/Events/EventNameExtractorResult.cs create mode 100644 src/Umbraco.Tests/Scoping/EventNameExtractorTests.cs diff --git a/src/Umbraco.Core/Events/EventDefinition.cs b/src/Umbraco.Core/Events/EventDefinition.cs index e7da58f0b5..7a1d82fe8a 100644 --- a/src/Umbraco.Core/Events/EventDefinition.cs +++ b/src/Umbraco.Core/Events/EventDefinition.cs @@ -9,6 +9,7 @@ namespace Umbraco.Core.Events private readonly EventArgs _args; public EventDefinition(EventHandler trackedEvent, object sender, EventArgs args) + : base(sender, args) { _trackedEvent = trackedEvent; _sender = sender; @@ -31,6 +32,7 @@ namespace Umbraco.Core.Events private readonly TEventArgs _args; public EventDefinition(EventHandler trackedEvent, object sender, TEventArgs args) + : base(sender, args) { _trackedEvent = trackedEvent; _sender = sender; @@ -53,6 +55,7 @@ namespace Umbraco.Core.Events private readonly TEventArgs _args; public EventDefinition(TypedEventHandler trackedEvent, TSender sender, TEventArgs args) + : base(sender, args) { _trackedEvent = trackedEvent; _sender = sender; diff --git a/src/Umbraco.Core/Events/EventDefinitionBase.cs b/src/Umbraco.Core/Events/EventDefinitionBase.cs index 754ed2fce5..f2d0c817de 100644 --- a/src/Umbraco.Core/Events/EventDefinitionBase.cs +++ b/src/Umbraco.Core/Events/EventDefinitionBase.cs @@ -4,18 +4,38 @@ namespace Umbraco.Core.Events { public abstract class EventDefinitionBase : IEventDefinition, IEquatable { - protected EventDefinitionBase() + protected EventDefinitionBase(object sender, object args, string eventName) { - EventId = Guid.NewGuid(); + if (sender == null) throw new ArgumentNullException("sender"); + if (eventName == null) throw new ArgumentNullException("eventName"); + Sender = sender; + Args = args; + EventName = eventName; } - public Guid EventId { get; private set; } + + protected EventDefinitionBase(object sender, object args) + { + if (sender == null) throw new ArgumentNullException("sender"); + if (args == null) throw new ArgumentNullException("args"); + Sender = sender; + Args = args; + var findResult = EventNameExtractor.FindEvent(sender, args, EventNameExtractor.MatchIngNames); + if (findResult.Success == false) + throw new InvalidOperationException("Could not automatically find the event name, the event name will need to be explicitly registered for this event definition. Error: " + findResult.Result.Error); + EventName = findResult.Result.Name; + } + + public object Sender { get; private set; } + public object Args { get; private set; } + public string EventName { get; private set; } + public abstract void RaiseEvent(); public bool Equals(EventDefinitionBase other) { if (ReferenceEquals(null, other)) return false; if (ReferenceEquals(this, other)) return true; - return EventId.Equals(other.EventId); + return Sender.Equals(other.Sender) && string.Equals(EventName, other.EventName); } public override bool Equals(object obj) @@ -28,7 +48,10 @@ namespace Umbraco.Core.Events public override int GetHashCode() { - return EventId.GetHashCode(); + unchecked + { + return (Sender.GetHashCode() * 397) ^ EventName.GetHashCode(); + } } public static bool operator ==(EventDefinitionBase left, EventDefinitionBase right) @@ -38,7 +61,7 @@ namespace Umbraco.Core.Events public static bool operator !=(EventDefinitionBase left, EventDefinitionBase right) { - return Equals(left, right) == false; + return !Equals(left, right); } } } \ No newline at end of file diff --git a/src/Umbraco.Core/Events/EventNameExtractor.cs b/src/Umbraco.Core/Events/EventNameExtractor.cs new file mode 100644 index 0000000000..606a3534cb --- /dev/null +++ b/src/Umbraco.Core/Events/EventNameExtractor.cs @@ -0,0 +1,150 @@ +using System; +using System.Collections.Concurrent; +using System.Linq; +using System.Reflection; +using System.Text.RegularExpressions; + +namespace Umbraco.Core.Events +{ + /// + /// There is actually no way to discover an event name in c# at the time of raising the event. It is possible + /// to get the event name from the handler that is being executed based on the event being raised, however that is not + /// what we want in this case. We need to find the event name before it is being raised - you would think that it's possible + /// with reflection or anything but that is not the case, the delegate that defines an event has no info attached to it, it + /// is literally just an event. + /// + /// So what this does is take the sender and event args objects, looks up all public/static events on the sender that have + /// a generic event handler with generic arguments (but only) one, then we match the type of event arguments with the ones + /// being passed in. As it turns out, in our services this will work for the majority of our events! In some cases it may not + /// work and we'll have to supply a string but hopefully this saves a bit of magic strings. + /// + /// We can also write tests to validate these are all working correctly for all services. + /// + internal class EventNameExtractor + { + /// + /// Finds the event name on the sender that matches the args type + /// + /// + /// + /// + /// A filter to exclude matched event names, this filter should return true to exclude the event name from being matched + /// + /// + /// null if not found or an ambiguous match + /// + public static Attempt FindEvent(object sender, object args, Func exclude) + { + var argsType = args.GetType(); + + //there is no way we can find a matching event if the argument type is not generic + if (argsType.IsGenericType == false) + return Attempt.Fail(new EventNameExtractorResult(EventNameExtractorError.UnsupportedArgType)); + + var senderType = sender.GetType(); + + var found = MatchedEventNames.GetOrAdd(new Tuple(senderType, argsType), tuple => + { + var events = CandidateEvents.GetOrAdd(senderType, t => + { + return t.GetEvents(BindingFlags.Static | BindingFlags.Public) + //we can only look for events handlers with generic types because that is the only + // way that we can try to find a matching event based on the arg type passed in + .Where(x => x.EventHandlerType.IsGenericType) + .Select(x => new EventInfoArgs(x, x.EventHandlerType.GetGenericArguments())) + //we are only looking for event handlers that have more than one generic argument + .Where(x => + { + if (x.GenericArgs.Length == 1) return true; + + //special case for our own TypedEventHandler + if (x.EventInfo.EventHandlerType.GetGenericTypeDefinition() == typeof(TypedEventHandler<,>) && x.GenericArgs.Length == 2) + { + return true; + } + + return false; + }) + .ToArray(); + }); + + return events.Where(x => + { + if (x.GenericArgs.Length == 1 && x.GenericArgs[0] == tuple.Item2) + return true; + + //special case for our own TypedEventHandler + if (x.EventInfo.EventHandlerType.GetGenericTypeDefinition() == typeof(TypedEventHandler<,>) + && x.GenericArgs.Length == 2 + && x.GenericArgs[1] == tuple.Item2) + { + return true; + } + + return false; + }).Select(x => x.EventInfo.Name).ToArray(); + }); + + var filtered = found.Where(x => exclude(x) == false).ToArray(); + + if (filtered.Length == 0) + return Attempt.Fail(new EventNameExtractorResult(EventNameExtractorError.NoneFound)); + + if (filtered.Length == 1) + return Attempt.Succeed(new EventNameExtractorResult(filtered[0])); + + //there's more than one left so it's ambiguous! + return Attempt.Fail(new EventNameExtractorResult(EventNameExtractorError.Ambiguous)); + } + + /// + /// Return true if the event is named with an ING name such as "Saving" or "RollingBack" + /// + /// + /// + internal static bool MatchIngNames(string eventName) + { + var splitter = new Regex(@"(? + /// Return true if the event is not named with an ING name such as "Saving" or "RollingBack" + /// + /// + /// + internal static bool MatchNonIngNames(string eventName) + { + var splitter = new Regex(@"(? + /// Used to cache all candidate events for a given type so we don't re-look them up + /// + private static readonly ConcurrentDictionary CandidateEvents = new ConcurrentDictionary(); + + /// + /// Used to cache all matched event names by (sender type + arg type) so we don't re-look them up + /// + private static readonly ConcurrentDictionary, string[]> MatchedEventNames = new ConcurrentDictionary, string[]>(); + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Events/EventNameExtractorError.cs b/src/Umbraco.Core/Events/EventNameExtractorError.cs new file mode 100644 index 0000000000..13cae1da71 --- /dev/null +++ b/src/Umbraco.Core/Events/EventNameExtractorError.cs @@ -0,0 +1,9 @@ +namespace Umbraco.Core.Events +{ + internal enum EventNameExtractorError + { + UnsupportedArgType, + NoneFound, + Ambiguous + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Events/EventNameExtractorResult.cs b/src/Umbraco.Core/Events/EventNameExtractorResult.cs new file mode 100644 index 0000000000..6213882d1f --- /dev/null +++ b/src/Umbraco.Core/Events/EventNameExtractorResult.cs @@ -0,0 +1,18 @@ +namespace Umbraco.Core.Events +{ + internal class EventNameExtractorResult + { + public EventNameExtractorError? Error { get; private set; } + public string Name { get; private set; } + + public EventNameExtractorResult(string name) + { + Name = name; + } + + public EventNameExtractorResult(EventNameExtractorError error) + { + Error = error; + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Events/IEventDefinition.cs b/src/Umbraco.Core/Events/IEventDefinition.cs index 9d3a6426fa..eb4fe65eb8 100644 --- a/src/Umbraco.Core/Events/IEventDefinition.cs +++ b/src/Umbraco.Core/Events/IEventDefinition.cs @@ -4,7 +4,9 @@ namespace Umbraco.Core.Events { public interface IEventDefinition { - Guid EventId { get; } + object Sender { get; } + object Args { get; } + string EventName { get; } void RaiseEvent(); } diff --git a/src/Umbraco.Core/Events/ScopedEventManager.cs b/src/Umbraco.Core/Events/ScopedEventManager.cs index 354858cdb1..3f8409e08a 100644 --- a/src/Umbraco.Core/Events/ScopedEventManager.cs +++ b/src/Umbraco.Core/Events/ScopedEventManager.cs @@ -39,5 +39,7 @@ namespace Umbraco.Core.Events { _tracked.Clear(); } + + } } \ No newline at end of file diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 88555db603..8996537b6c 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -315,6 +315,9 @@ + + + diff --git a/src/Umbraco.Tests/Scoping/EventNameExtractorTests.cs b/src/Umbraco.Tests/Scoping/EventNameExtractorTests.cs new file mode 100644 index 0000000000..3faeb51d17 --- /dev/null +++ b/src/Umbraco.Tests/Scoping/EventNameExtractorTests.cs @@ -0,0 +1,51 @@ +using System; +using NUnit.Framework; +using Umbraco.Core.Events; + +namespace Umbraco.Tests.Scoping +{ + [TestFixture] + public class EventNameExtractorTests + { + [Test] + public void Find_Event_Ing() + { + var found = EventNameExtractor.FindEvent(this, new SaveEventArgs("test"), EventNameExtractor.MatchIngNames); + Assert.IsTrue(found.Success); + Assert.AreEqual("FoundMe", found.Result.Name); + } + + [Test] + public void Find_Event_Non_Ing() + { + var found = EventNameExtractor.FindEvent(this, new SaveEventArgs("test"), EventNameExtractor.MatchNonIngNames); + Assert.IsTrue(found.Success); + Assert.AreEqual("FindingMe", found.Result.Name); + } + + [Test] + public void Ambiguous_Match() + { + var found = EventNameExtractor.FindEvent(this, new SaveEventArgs(0), EventNameExtractor.MatchIngNames); + Assert.IsFalse(found.Success); + Assert.AreEqual(EventNameExtractorError.Ambiguous, found.Result.Error); + } + + [Test] + public void No_Match() + { + var found = EventNameExtractor.FindEvent(this, new SaveEventArgs(0), EventNameExtractor.MatchIngNames); + Assert.IsFalse(found.Success); + Assert.AreEqual(EventNameExtractorError.NoneFound, found.Result.Error); + } + + public static event EventHandler> FindingMe; + public static event EventHandler> FoundMe; + + //will lead to ambiguous matches + public static event EventHandler> SavingThis; + public static event EventHandler> SavedThis; + public static event EventHandler> SavingThat; + public static event EventHandler> SavedThat; + } +} \ No newline at end of file diff --git a/src/Umbraco.Tests/Scoping/ScopedEventManagerTests.cs b/src/Umbraco.Tests/Scoping/ScopedEventManagerTests.cs index 3ddd0f7e08..c98b05600e 100644 --- a/src/Umbraco.Tests/Scoping/ScopedEventManagerTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopedEventManagerTests.cs @@ -1,4 +1,10 @@ using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Text.RegularExpressions; using Moq; using NUnit.Framework; using Umbraco.Core.Events; @@ -8,9 +14,18 @@ using Umbraco.Core.Scoping; namespace Umbraco.Tests.Scoping { + [TestFixture] public class ScopedEventManagerTests { + [SetUp] + public void Setup() + { + //remove all handlers first + DoThing1 = null; + DoThing2 = null; + DoThing3 = null; + } [Test] public void Does_Not_Support_Event_Cancellation() @@ -22,19 +37,46 @@ namespace Umbraco.Tests.Scoping } } + [Test] - public void Does_Not_Immediately_Raise_Events() + public void Can_Get_Event_Info() { - this.DoThing1 += OnDoThingFail; - this.DoThing2 += OnDoThingFail; - this.DoThing3 += OnDoThingFail; + DoThing1 += OnDoThingFail; + DoThing2 += OnDoThingFail; + DoThing3 += OnDoThingFail; var provider = new PetaPocoUnitOfWorkProvider(new ScopeProvider(Mock.Of())); using (var uow = provider.GetUnitOfWork()) { - uow.EventManager.TrackEvent(DoThing1, this, new EventArgs()); - uow.EventManager.TrackEvent(DoThing2, this, new EventArgs()); - uow.EventManager.TrackEvent(DoThing3, this, new EventArgs()); + uow.EventManager.TrackEvent(DoThing1, this, new SaveEventArgs("test")); + uow.EventManager.TrackEvent(DoThing2, this, new SaveEventArgs(0)); + uow.EventManager.TrackEvent(DoThing3, this, new SaveEventArgs(0)); + + var e = uow.EventManager.GetEvents().ToArray(); + var knownNames = new [] {"DoThing1", "DoThing2", "DoThing3"}; + var knownArgTypes = new [] { typeof(SaveEventArgs), typeof(SaveEventArgs), typeof(SaveEventArgs) }; + + for (int i = 0; i < e.Length; i++) + { + Assert.AreEqual(knownNames[i], e[i].EventName); + Assert.AreEqual(knownArgTypes[i], e[i].Args.GetType()); + } + } + } + + [Test] + public void Does_Not_Immediately_Raise_Events() + { + DoThing1 += OnDoThingFail; + DoThing2 += OnDoThingFail; + DoThing3 += OnDoThingFail; + + var provider = new PetaPocoUnitOfWorkProvider(new ScopeProvider(Mock.Of())); + using (var uow = provider.GetUnitOfWork()) + { + uow.EventManager.TrackEvent(DoThing1, this, new SaveEventArgs("test")); + uow.EventManager.TrackEvent(DoThing2, this, new SaveEventArgs(0)); + uow.EventManager.TrackEvent(DoThing3, this, new SaveEventArgs(0)); Assert.Pass(); } @@ -45,17 +87,17 @@ namespace Umbraco.Tests.Scoping { var counter = 0; - this.DoThing1 += (sender, args) => + DoThing1 += (sender, args) => { counter++; }; - this.DoThing2 += (sender, args) => + DoThing2 += (sender, args) => { counter++; }; - this.DoThing3 += (sender, args) => + DoThing3 += (sender, args) => { counter++; }; @@ -63,9 +105,9 @@ namespace Umbraco.Tests.Scoping var provider = new PetaPocoUnitOfWorkProvider(new ScopeProvider(Mock.Of())); using (var uow = provider.GetUnitOfWork()) { - uow.EventManager.TrackEvent(DoThing1, this, new EventArgs()); - uow.EventManager.TrackEvent(DoThing2, this, new EventArgs()); - uow.EventManager.TrackEvent(DoThing3, this, new EventArgs()); + uow.EventManager.TrackEvent(DoThing1, this, new SaveEventArgs("test")); + uow.EventManager.TrackEvent(DoThing2, this, new SaveEventArgs(0)); + uow.EventManager.TrackEvent(DoThing3, this, new SaveEventArgs(0)); Assert.AreEqual(0, counter); @@ -83,8 +125,12 @@ namespace Umbraco.Tests.Scoping Assert.Fail(); } - public event EventHandler DoThing1; - public event EventHandler DoThing2; - public event TypedEventHandler DoThing3; + + public static event EventHandler> DoThing1; + + public static event EventHandler> DoThing2; + + public static event TypedEventHandler> DoThing3; } + } \ No newline at end of file diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj index 45cfc6cfd7..49ad8047cb 100644 --- a/src/Umbraco.Tests/Umbraco.Tests.csproj +++ b/src/Umbraco.Tests/Umbraco.Tests.csproj @@ -169,6 +169,7 @@ +