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..7a1d82fe8a --- /dev/null +++ b/src/Umbraco.Core/Events/EventDefinition.cs @@ -0,0 +1,73 @@ +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) + : base(sender, 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) + : base(sender, 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) + : base(sender, 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..f2d0c817de --- /dev/null +++ b/src/Umbraco.Core/Events/EventDefinitionBase.cs @@ -0,0 +1,67 @@ +using System; + +namespace Umbraco.Core.Events +{ + public abstract class EventDefinitionBase : IEventDefinition, IEquatable + { + protected EventDefinitionBase(object sender, object args, string eventName) + { + if (sender == null) throw new ArgumentNullException("sender"); + if (eventName == null) throw new ArgumentNullException("eventName"); + Sender = sender; + Args = args; + EventName = eventName; + } + + 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 Sender.Equals(other.Sender) && string.Equals(EventName, other.EventName); + } + + 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() + { + unchecked + { + return (Sender.GetHashCode() * 397) ^ EventName.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); + } + } +} \ 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/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 new file mode 100644 index 0000000000..eb4fe65eb8 --- /dev/null +++ b/src/Umbraco.Core/Events/IEventDefinition.cs @@ -0,0 +1,13 @@ +using System; + +namespace Umbraco.Core.Events +{ + public interface IEventDefinition + { + object Sender { get; } + object Args { get; } + string EventName { 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..d22d31f930 --- /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 : IDisposable + { + 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..27bb68f8e6 --- /dev/null +++ b/src/Umbraco.Core/Events/NoScopedEventManager.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Umbraco.Core.Events +{ + /// + /// 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) + { + 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; } + } + + 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 new file mode 100644 index 0000000000..3f8409e08a --- /dev/null +++ b/src/Umbraco.Core/Events/ScopedEventManager.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; + +namespace Umbraco.Core.Events +{ + /// + /// 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) + { + _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; } + } + + protected override void DisposeResources() + { + _tracked.Clear(); + } + + + } +} \ 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/LockingRepository.cs b/src/Umbraco.Core/Persistence/LockingRepository.cs index 09195f8ce6..6d3d5d54c1 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 Func _repositoryFactory; + 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/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 a053cbe977..ee19161ae0 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 ac5cd83a46..08257940a2 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 57f96ea2f0..b440d477a5 100644 --- a/src/Umbraco.Core/Persistence/Repositories/ContentTypeRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/ContentTypeRepository.cs @@ -19,7 +19,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 4bf27f04cd..071bf7eba8 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 d2cc92ff0b..2c6313f3d1 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) { } @@ -289,7 +289,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; @@ -341,7 +341,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 75c6ad0d87..3dca2ffdd0 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 41910e507a..ec86311771 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 a32a3c4647..8b32f4fd1f 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 1125b7f61a..17aa20a208 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 edf7051d4f..11542673be 100644 --- a/src/Umbraco.Core/Persistence/Repositories/MediaTypeRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/MediaTypeRepository.cs @@ -22,7 +22,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 b98b20ae3f..9a917b3ea4 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 aceef3518b..c2f5c09dcf 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 49c9d47319..7e0e11173d 100644 --- a/src/Umbraco.Core/Persistence/Repositories/MemberTypeRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/MemberTypeRepository.cs @@ -21,7 +21,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 c02316e7f4..2a34aeb153 100644 --- a/src/Umbraco.Core/Persistence/Repositories/PetaPocoRepositoryBase.cs +++ b/src/Umbraco.Core/Persistence/Repositories/PetaPocoRepositoryBase.cs @@ -19,7 +19,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"); @@ -27,11 +27,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 a4f8705f81..ee045c725f 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 198afa818b..ba578b93f1 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 9833a36bf8..7d33697e72 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 _globalCache; - public ServerRegistrationRepository(IDatabaseUnitOfWork work, ICacheProvider globalCache, ILogger logger, ISqlSyntaxProvider sqlSyntax) + public ServerRegistrationRepository(IDatabaseUnitOfWork work, ICacheProvider staticCache, ILogger logger, ISqlSyntaxProvider sqlSyntax) : base(work, CacheHelper.NoCache, logger, sqlSyntax) { // managing the cache our own way (no policy etc) 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 45a402d36f..c9c11e5fae 100644 --- a/src/Umbraco.Core/Persistence/Repositories/TemplateRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/TemplateRepository.cs @@ -30,7 +30,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 e12a427202..07028663e3 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, _nullCache, //never cache _logger, _sqlSyntax); } - public virtual IAuditRepository CreateAuditRepository(IDatabaseUnitOfWork uow) + public virtual IAuditRepository CreateAuditRepository(IScopeUnitOfWork uow) { return new AuditRepository(uow, _nullCache, //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, _nullCache, //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 new file mode 100644 index 0000000000..e5a76cc94e --- /dev/null +++ b/src/Umbraco.Core/Persistence/UnitOfWork/IScopeUnitOfWork.cs @@ -0,0 +1,9 @@ +using Umbraco.Core.Events; + +namespace Umbraco.Core.Persistence.UnitOfWork +{ + public 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..b6f8335e1a --- /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 + /// + public 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 b9564e92cb..6276898afc 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; @@ -9,8 +10,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 +28,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 /// @@ -154,12 +156,17 @@ namespace Umbraco.Core.Persistence.UnitOfWork get { return Scope.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. @@ -197,5 +204,6 @@ namespace Umbraco.Core.Persistence.UnitOfWork _scope.Dispose(); _scope = null; } - } + + } } \ 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 4d1b638016..7bcfcba2b9 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) @@ -55,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. @@ -65,27 +73,26 @@ 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() + public IScopeUnitOfWork GetUnitOfWork() { return new PetaPocoUnitOfWork(_scopeProvider); } - public IDatabaseUnitOfWork GetUnitOfWork(IsolationLevel isolationLevel) + /// + /// 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); } #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/Scoping/IScope.cs b/src/Umbraco.Core/Scoping/IScope.cs index 058b45998f..db68d4ed78 100644 --- a/src/Umbraco.Core/Scoping/IScope.cs +++ b/src/Umbraco.Core/Scoping/IScope.cs @@ -31,6 +31,11 @@ namespace Umbraco.Core.Scoping /// IsolatedRuntimeCache IsolatedRuntimeCache { 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 fd0547b2d2..5e5c8aab21 100644 --- a/src/Umbraco.Core/Scoping/NoScope.cs +++ b/src/Umbraco.Core/Scoping/NoScope.cs @@ -15,6 +15,7 @@ namespace Umbraco.Core.Scoping private bool _disposed; private UmbracoDatabase _database; + private IEventManager _eventManager; private IList _messages; public NoScope(ScopeProvider scopeProvider) @@ -67,7 +68,7 @@ namespace Umbraco.Core.Scoping return _messages ?? (_messages = new List()); } } - + public IList MessagesOrNull { get @@ -77,6 +78,16 @@ namespace Umbraco.Core.Scoping } } + /// + public IEventManager EventManager + { + get + { + EnsureNotDisposed(); + return _eventManager ?? (_eventManager = new NoScopedEventManager()); + } + } + /// public void Complete() { @@ -119,6 +130,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 b375f72bbf..90aac6617b 100644 --- a/src/Umbraco.Core/Scoping/Scope.cs +++ b/src/Umbraco.Core/Scoping/Scope.cs @@ -23,6 +23,7 @@ namespace Umbraco.Core.Scoping private UmbracoDatabase _database; private IList _messages; private IDictionary> _exitActions; + private IEventManager _eventManager; // this is v7, in v8 this has to change to RepeatableRead private const IsolationLevel DefaultIsolationLevel = IsolationLevel.ReadCommitted; @@ -186,6 +187,15 @@ namespace Umbraco.Core.Scoping } } + public IEventManager EventManager + { + get + { + EnsureNotDisposed(); + return _eventManager ?? (_eventManager = new ScopedEventManager()); + } + } + /// public void Complete() { @@ -230,6 +240,11 @@ namespace Umbraco.Core.Scoping else DisposeLastScope(); + if (_eventManager != null) + { + _eventManager.Dispose(); + } + _disposed = true; GC.SuppressFinalize(this); } 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..343b4b66ad 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(); @@ -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); 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/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/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/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/Services/ServerRegistrationService.cs b/src/Umbraco.Core/Services/ServerRegistrationService.cs index b2d5ca855e..fbd737fdf7 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 }; @@ -31,13 +31,13 @@ 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, x => RepositoryFactory.CreateServerRegistrationRepository(x), LockingRepositoryIds, LockingRepositoryIds); - } + } /// /// Touches a server to mark it as active; deactivate stale servers. 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.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 diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index d3b90a27c3..4cbc3ddf5d 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -310,14 +310,23 @@ + + + + + + + + + - + @@ -501,6 +510,8 @@ + + @@ -565,6 +576,7 @@ + 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/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/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 d76c14e189..ec1b4885ef 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..c98b05600e --- /dev/null +++ b/src/Umbraco.Tests/Scoping/ScopedEventManagerTests.cs @@ -0,0 +1,136 @@ +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; +using Umbraco.Core.Persistence; +using Umbraco.Core.Persistence.UnitOfWork; +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() + { + var provider = new PetaPocoUnitOfWorkProvider(new ScopeProvider(Mock.Of())); + using (var uow = provider.GetUnitOfWork()) + { + Assert.IsFalse(uow.EventManager.SupportsEventCancellation); + } + } + + + [Test] + public void Can_Get_Event_Info() + { + 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)); + + 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(); + } + } + + [Test] + public void Can_Raise_Events_Later() + { + var counter = 0; + + DoThing1 += (sender, args) => + { + counter++; + }; + + DoThing2 += (sender, args) => + { + counter++; + }; + + DoThing3 += (sender, args) => + { + counter++; + }; + + 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.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 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/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/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj index 696964d0a9..cbc4cdd1f3 100644 --- a/src/Umbraco.Tests/Umbraco.Tests.csproj +++ b/src/Umbraco.Tests/Umbraco.Tests.csproj @@ -169,8 +169,11 @@ + + + diff --git a/src/Umbraco.Tests/Web/Mvc/UmbracoViewPageTests.cs b/src/Umbraco.Tests/Web/Mvc/UmbracoViewPageTests.cs index 6d776b6d35..f83b8a6369 100644 --- a/src/Umbraco.Tests/Web/Mvc/UmbracoViewPageTests.cs +++ b/src/Umbraco.Tests/Web/Mvc/UmbracoViewPageTests.cs @@ -393,10 +393,10 @@ 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, + new Mock().Object, new RepositoryFactory(CacheHelper.CreateDisabledCacheHelper(), logger, Mock.Of(), umbracoSettings), logger, new TransientMessagesFactory(),