Exemple #1
0
        public static Snapshot ToSnapshot(this IAggregateRoot aggregate)
        {
            var data     = JsonConvert.SerializeObject(aggregate, SerializerSettings);
            var metadata = JsonConvert.SerializeObject(aggregate.GetType().AssemblyQualifiedName, SerializerSettings);

            return(new Snapshot(Guid.NewGuid(), aggregate.Id, aggregate.GetType().Name, aggregate.Version, data, metadata, DateTime.Now));
        }
Exemple #2
0
        private bool TryGetFromSnapshot(string aggregateRootId, Type aggregateRootType, out IAggregateRoot aggregateRoot)
        {
            aggregateRoot = _aggregateSnapshotter.RestoreFromSnapshot(aggregateRootType, aggregateRootId);

            if (aggregateRoot == null)
            {
                return(false);
            }

            if (aggregateRoot.GetType() != aggregateRootType || aggregateRoot.UniqueId != aggregateRootId)
            {
                throw new Exception(string.Format("AggregateRoot recovery from snapshot is invalid as the aggregateRootType or aggregateRootId is not matched. Snapshot: [aggregateRootType:{0},aggregateRootId:{1}], expected: [aggregateRootType:{2},aggregateRootId:{3}]",
                                                  aggregateRoot.GetType(),
                                                  aggregateRoot.UniqueId,
                                                  aggregateRootType,
                                                  aggregateRootId));
            }

            var aggregateRootTypeName     = _typeNameProvider.GetTypeName(aggregateRootType);
            var eventStreamsAfterSnapshot = _eventStore.QueryAggregateEvents(aggregateRootId, aggregateRootTypeName, aggregateRoot.Version + 1, int.MaxValue);

            aggregateRoot.ReplayEvents(eventStreamsAfterSnapshot);

            return(true);
        }
        public async Task <int> Save(IAggregateRoot aggregateRoot)
        {
            var dt = new DataTable();

            dt.Columns.Add("Data", typeof(string));

            foreach (var e in aggregateRoot.GetEvents())
            {
                dt.Rows.Add(e.Serialize());
            }

            using (var connection = new SqlConnection(_connectionString))
            {
                var argumentObject = new
                {
                    AggregateID = aggregateRoot.Id,
                    Name        = StreamName(aggregateRoot.GetType(), aggregateRoot.Id),
                    Type        = aggregateRoot.GetType().AssemblyQualifiedName,
                    aggregateRoot.Version,
                    Batch = dt.AsTableValuedParameter("EventValueType")
                };

                return(await connection.ExecuteAsync("Event_Ins", argumentObject, commandType : CommandType.StoredProcedure));
            }
        }
Exemple #4
0
        private IAggregateSnapshot BuildSnapshotFromAggregate(IAggregateRoot aggregate)
        {
            var aggregateTypeName = aggregate.GetType().Name.Substring(aggregate.GetType().Name.LastIndexOf(".") + 1);
            var snapshotTypeName  = $"ProgramaPontos.Domain.Snapshots.{aggregateTypeName}Snapshot, ProgramaPontos.Domain";
            var snapshotType      = Type.GetType(snapshotTypeName);

            return((IAggregateSnapshot)Activator.CreateInstance(snapshotType, aggregate));
        }
Exemple #5
0
 public Aggregate(string identifier, Version expectedVersion, IAggregateRoot root)
 {
     this.Identifier      = identifier ?? throw new ArgumentNullException(nameof(identifier));
     this.ExpectedVersion = expectedVersion;
     this.Root            = root ?? throw new ArgumentNullException(nameof(root));
     this.RootType        = root.GetType().Name;
 }
Exemple #6
0
        /// <summary>
        ///     Registers the specified aggregate.
        /// </summary>
        /// <param name="aggregate">The aggregate.</param>
        /// <exception cref="System.ArgumentNullException">Aggregate null exception.</exception>
        public virtual void Register(IAggregateRoot aggregate)
        {
            if (aggregate == null)
            {
                throw new ArgumentNullException("aggregate");
            }

            _registered = aggregate;

            // Get instance methods named Apply with one parameter returning void
            var applyMethods = aggregate.GetType()
                               .GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
                               .Where(m => m.Name == "Apply" && m.GetParameters().Length == 1 && m.ReturnType == typeof(void))
                               .Select(
                m => new
            {
                Method      = m,
                MessageType = m.GetParameters().Single().ParameterType
            });

            foreach (var apply in applyMethods)
            {
                var applyMethod = apply.Method;
                _handlers.Add(apply.MessageType, m => applyMethod.Invoke(aggregate, new[] { m }));
            }
        }
Exemple #7
0
        private static void UpdateStream(IAggregateRoot stream, Guid commandId)
        {
            var notCommited = stream.NotCommitedChanges().ToList();

            if (!notCommited.Any())
            {
                return;
            }

            var versionCnt = stream.Metadata.Version;

            foreach (var bEvent in notCommited)
            {
                var aggregateType = stream.GetType().FullName;
                var new_version   = ++versionCnt;

                bEvent.EventId  = $"{stream.Metadata.AggregateId}_{new_version}";
                bEvent.Metadata = new SourcedEventMetadata
                {
                    Version       = new_version,
                    CommandId     = commandId,
                    AggregateId   = stream.Metadata.AggregateId,
                    AggregateType = aggregateType,
                    Date          = DateTime.UtcNow
                };
            }
        }
        /// <summary>
        ///     Saves the specified aggregate.
        /// </summary>
        /// <param name="aggregate">The aggregate.</param>
        /// <param name="uncommitedEvents">The uncommited events.</param>
        /// <param name="commitId">The commit id.</param>
        /// <param name="updateHeaders">The update headers.</param>
        /// <exception cref="ProCenter.Infrastructure.EventStore.ConflictingCommandException"></exception>
        /// <exception cref="ProCenter.Infrastructure.EventStore.PersistenceException"></exception>
        public virtual void Save(IAggregateRoot aggregate, IEnumerable <IDomainEvent> uncommitedEvents, Guid commitId, Action <IDictionary <string, object> > updateHeaders)
        {
            var headers    = PrepareHeaders(aggregate, updateHeaders);
            var eventStore = _eventStoreFactory.Build(aggregate.GetType());

            while (true)
            {
                var stream           = PrepareStream(eventStore, aggregate, headers, uncommitedEvents);
                var commitEventCount = stream.CommittedEvents.Count;

                try
                {
                    stream.CommitChanges(commitId);
                    return;
                }
                catch (DuplicateCommitException)
                {
                    stream.ClearChanges();
                    return;
                }
                catch (ConcurrencyException e)
                {
                    if (this.ThrowOnConflict(stream, commitEventCount))
                    {
                        throw new ConflictingCommandException(e.Message, e);
                    }

                    stream.ClearChanges();
                }
                catch (StorageException e)
                {
                    throw new PersistenceException(e.Message, e);
                }
            }
        }
        public void Save(IAggregateRoot aggregateRoot)
        {
            var set = _cache.GetOrAdd(aggregateRoot.GetType(), () => new HashSet <IAggregateRoot>());

            if (!set.Add(aggregateRoot))
            {
                return;
            }

            var eventPublisher = aggregateRoot as IEventPublisher;

            if (eventPublisher == null)
            {
                return;
            }

            var events = eventPublisher.GetEvents();

            if (events.IsEmpty())
            {
                return;
            }

            _eventBus.Publish(events);
        }
Exemple #10
0
        private async Task<List<IEventMessageDraft>> CreateEventMessagesAsync(IAggregateRoot aggregate, IReadOnlyCollection<DomainAggregateEvent> events)
        {
            var messages = new List<IEventMessageDraft>();
            Guid? aggregateClassId = entityTypeManager.TryGetClassInfoByClrType(aggregate.GetType())?.Id;

            foreach (DomainAggregateEvent ev in events)
            {
                IEventMessageDraft message = await eventMessageFactory.CreateMessageAsync(ev);
                if (aggregateClassId != null)
                {
                    message.SetMetadata(BasicEventMetadataNames.AggregateClassId, aggregateClassId.Value.ToString());
                }
                
                if (aggregate is ITenantOwned tenantOwned)
                {
                    message.SetMetadata(BasicEventMetadataNames.AggregateTenantId, tenantOwned.TenantId?.ToString());
                }

                if (message.Metadata.GetEventId() == null)
                {
                    message.SetMetadata(BasicEventMetadataNames.EventId, Guid.NewGuid().ToString());
                }

                messages.Add(message);
            }

            return messages;
        }
Exemple #11
0
 private MethodInfo FindApply(object eventMessage)
 {
     return((from methodInfo in _aggregateRoot.GetType().GetMethods(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public)
             from parameterInfo in methodInfo.GetParameters()
             where parameterInfo.ParameterType == eventMessage.GetType() && methodInfo.Name.Contains("Handle")
             select methodInfo).Single());
 }
Exemple #12
0
 public bool Exists(IAggregateRoot aggregate)
 {
     if (aggregate == null)
     {
         return(false);
     }
     return(_memoryCache.TryGetValue(CacheKey(aggregate.GetType(), aggregate.Id), out object value));
 }
Exemple #13
0
 public IAggregateRoot Set(IAggregateRoot aggregate)
 {
     if (aggregate == null)
     {
         return(null);
     }
     return(this.Set(aggregate.GetType(), aggregate.Id, aggregate));
 }
Exemple #14
0
            public async Task AppendUncommittedEventsToNewStream([Frozen] IEventStoreConnection connection,
                                                                 IAggregateRoot <TestAggregate> aggregateRoot, EventStoreRepository sut)
            {
                await sut.SaveAsync(aggregateRoot);

                await connection.Received(1).AppendToStreamAsync($"{aggregateRoot.GetType().Name}-{aggregateRoot.Id}",
                                                                 aggregateRoot.OriginalVersion, aggregateRoot.GetUncommittedEvents());
            }
Exemple #15
0
 Task IUnitOfWorkRepository.PersistUpdateOfAsync(IAggregateRoot entity, IDbConnection dbConnection, IDbTransaction dbTransaction)
 {
     if (entity is TEntity == false)
     {
         throw new System.Exception($"Expecting {typeof(TEntity).Name} but {entity.GetType().Name}");
     }
     return(PersistUpdateOfAsync((TEntity)entity, dbConnection, dbTransaction));
 }
Exemple #16
0
        public Task Save(IAggregateRoot aggregateRoot)
        {
            var events = aggregateRoot
                         .GetEvents()
                         .Select(ToEventData);

            return(eventStoreConnection.AppendToStreamAsync(StreamName(aggregateRoot.GetType(), aggregateRoot.Id), aggregateRoot.Version, events));
        }
Exemple #17
0
        public void Add(IAggregateRoot aggregateRoot)
        {
            Assertions.NotNull(aggregateRoot, "aggregateRoot");

            var key = string.Concat(aggregateRoot.GetType().FullName, "@", aggregateRoot.Id);

            _trackingAggregateRoots.TryAdd(key, aggregateRoot);
        }
        public void Add(IAggregateRoot aggregate)
        {
            if (aggregate == null || !aggregate.GetType().Equals(typeof(TAggregateRoot)))
            {
                throw new Exception($"类型不是{typeof(TAggregateRoot).Name}");
            }

            this.Add((TAggregateRoot)aggregate);
        }
Exemple #19
0
        public SnapshotConfig GetConfiguration(IAggregateRoot aggregate)
        {
            if (entitySnapshotsConfigs.TryGetValue(aggregate.GetType(), out var config))
            {
                return(config);
            }

            return(defaultSnapshotConfig);
        }
 internal static AggregateSnapshot MakeSnapshot(this IAggregateRoot aggregate)
 {
     return(new AggregateSnapshot
     {
         AggregateId = aggregate.Id,
         AggregateType = aggregate.GetType(),
         Version = aggregate.Version,
         State = aggregate.State,
     });
 }
Exemple #21
0
 private DomainEventStreamMessage CreateMessage(IAggregateRoot aggregateRoot)
 {
     return new DomainEventStreamMessage(
         ObjectId.GenerateNewStringId(),
         aggregateRoot.UniqueId,
         aggregateRoot.Version + 1,
         aggregateRoot.GetType().FullName,
         aggregateRoot.GetChanges(),
         new Dictionary<string, string>());
 }
        public void Delete(IAggregateRoot aggregateRoot)
        {
            HashSet <IAggregateRoot> set;

            if (!_cache.TryGetValue(aggregateRoot.GetType(), out set))
            {
                return;
            }
            set.RemoveWhere(p => p.Id.GetHashCode() == aggregateRoot.Id.GetHashCode());
        }
Exemple #23
0
        public async Task TakeAndSaveAsync(IAggregateRoot aggregate)
        {
            var snapshot = aggregate.ToSnapshot();

            string insertScript = EventRepositoryScriptsAsStrings.InsertSnapshot();

            await _databaseProvider.ExecuteAsync(insertScript, snapshot);

            Log.Information($"Snapshot for aggregate {aggregate.GetType().Name} has been created from version {aggregate.Version}");
        }
 private DomainEventStreamMessage CreateMessage(IAggregateRoot aggregateRoot)
 {
     return(new DomainEventStreamMessage(
                ObjectId.GenerateNewStringId(),
                aggregateRoot.UniqueId,
                aggregateRoot.Version + 1,
                aggregateRoot.GetType().FullName,
                aggregateRoot.GetChanges(),
                new Dictionary <string, string>()));
 }
		public void Handle(IAggregateRoot root, IDomainEvent ev)
		{
			MethodInvoker invoker;
			if (!_handlers.TryGetValue(ev.GetType(), out invoker))
			{
				throw new InvalidOperationException(string.Format("Apply method for event [{0}] wasn't resolved in [{1}]", ev.GetType().Name, root.GetType().Name));
			}

			invoker.Invoke(root, new object[] {ev});
		}
 private DomainEventStream BuildDomainEventStream(IAggregateRoot aggregateRoot, IEnumerable <IDomainEvent> changedEvents, ProcessingCommand processingCommand)
 {
     return(new DomainEventStream(
                processingCommand.Message.Id,
                aggregateRoot.UniqueId,
                _aggregateRootTypeProvider.GetTypeCode(aggregateRoot.GetType()),
                aggregateRoot.Version + 1,
                DateTime.Now,
                changedEvents,
                processingCommand.Items));
 }
Exemple #27
0
        public Snapshot CreateSnapshot(IAggregateRoot aggregateRoot)
        {
            if (aggregateRoot == null)
            {
                throw new ArgumentNullException("aggregateRoot");
            }

            var payload = _binarySerializer.Serialize(aggregateRoot);
            var aggregateRootTypeCode = _aggregateRootTypeCodeProvider.GetTypeCode(aggregateRoot.GetType());

            return(new Snapshot(aggregateRootTypeCode, aggregateRoot.UniqueId, aggregateRoot.Version, payload, DateTime.Now));
        }
        public Snapshot CreateSnapshot(IAggregateRoot aggregateRoot)
        {
            if (aggregateRoot == null)
            {
                throw new ArgumentNullException("aggregateRoot");
            }

            var payload = _binarySerializer.Serialize(aggregateRoot);
            var aggregateRootTypeCode = _aggregateRootTypeCodeProvider.GetTypeCode(aggregateRoot.GetType());

            return new Snapshot(aggregateRootTypeCode, aggregateRoot.UniqueId, aggregateRoot.Version, payload, DateTime.Now);
        }
        private static Dictionary <string, object> PrepareHeaders(IAggregateRoot aggregate, Action <IDictionary <string, object> > updateHeaders)
        {
            var headers = new Dictionary <string, object> ();

            headers[AggregateTypeHeader] = aggregate.GetType().FullName;
            if (updateHeaders != null)
            {
                updateHeaders(headers);
            }

            return(headers);
        }
Exemple #30
0
        public async Task TakeSnapshotSync(IAggregateRoot aggregate)
        {
            if (!(aggregate is ISnapshotable))
            {
                return;
            }

            var takeSnapshotMethod = aggregate.GetType().GetMethod("TakeSnapshot");
            var memento            = (Memento)takeSnapshotMethod.Invoke(aggregate, new object[] { });

            await snapshotStore.Write(memento);
        }
        private bool TryGetFromSnapshot(string aggregateRootId, Type aggregateRootType, out IAggregateRoot aggregateRoot)
        {
            aggregateRoot = _aggregateSnapshotter.RestoreFromSnapshot(aggregateRootType, aggregateRootId);

            if (aggregateRoot == null) return false;

            if (aggregateRoot.GetType() != aggregateRootType || aggregateRoot.UniqueId != aggregateRootId)
            {
                throw new Exception(string.Format("AggregateRoot recovery from snapshot is invalid as the aggregateRootType or aggregateRootId is not matched. Snapshot: [aggregateRootType:{0},aggregateRootId:{1}], expected: [aggregateRootType:{2},aggregateRootId:{3}]",
                    aggregateRoot.GetType(),
                    aggregateRoot.UniqueId,
                    aggregateRootType,
                    aggregateRootId));
            }

            var aggregateRootTypeName = _typeNameProvider.GetTypeName(aggregateRootType);
            var eventStreamsAfterSnapshot = _eventStore.QueryAggregateEvents(aggregateRootId, aggregateRootTypeName, aggregateRoot.Version + 1, int.MaxValue);
            aggregateRoot.ReplayEvents(eventStreamsAfterSnapshot);

            return true;
        }
Exemple #32
0
        public IAggregateRoot Remove(IAggregateRoot aggregate)
        {
            if (aggregate == null)
            {
                return(null);
            }
            var key    = this.CacheKey(aggregate.GetType(), aggregate.Id);
            var result = this._memoryCache.Get <IAggregateRoot>(key);

            this._memoryCache.Remove(key);
            return(result);
        }
        private void PublishEvents(IAggregateRoot instance, IDomainNotification snapshotChange)
        {
            foreach (var evt in instance.UncommittedEvents.ToList())
            {
                var modelChange = NotificationExtensions.CreateNotification(instance.GetType(), evt);
                this.changes.OnNext(modelChange);
            }

            if (snapshotChange != null)
            {
                this.changes.OnNext(snapshotChange);
            }
        }
Exemple #34
0
        public static bool ShouldMakeSnapshot(IAggregateRoot aggregate)
        {
            if (!IsSnapshotable(aggregate.GetType()))
            {
                return(false);
            }

            if (aggregate.Version != 0 && aggregate.Version % _snapshotInterval == 0)
            {
                return(true);
            }
            return(false);
        }
		internal static void Apply(IAggregateRoot root, IDomainEvent ev)
		{
			var rootType = root.GetType();
			EventHandlerRegistry registry;
			if (!_handlers.TryGetValue(rootType, out registry))
			{
				registry = new EventHandlerRegistry(ApplyMethodResolver.ResolveAll(rootType));
				_handlers[rootType] = registry;
			}

			registry.Handle(root, ev);

			//ResolveApplyMethodDelegate(root.GetType(), ev.GetType())(root, ev);
		}
        private static string CreateMessage(IAggregateRoot aggRoot, Guid originalVersion, Guid currentVersion)
        {
            var aggType = aggRoot.GetType().Name;

            var msg = string.Format("The {0} you were trying to save has been updated by another user, you will have to start the editing process again to retry.", aggType);
            msg += Environment.NewLine;
            msg += Environment.NewLine;
            msg += "Aggregate ID: " + aggRoot.AggregateId.ToString();
            msg += Environment.NewLine;
            msg += "Original Version: " + originalVersion.ToString();
            msg += Environment.NewLine;
            msg += "Current Version: " + currentVersion.ToString();

            return msg;
        }
 public ConcurrencyException(IAggregateRoot aggregate)
     : base(string.Format("Two different versions of aggregate root {0} of type '{1}' was detected in one DataSession",
                 ((IEntity) aggregate).IdObject, aggregate.GetType().Name))
 {
     Aggregate = aggregate;
 }
 private void IncreaseAggregateVersion(IAggregateRoot aggregateRoot)
 {
     _increaseVersionMethodDict[aggregateRoot.GetType()](aggregateRoot);
 }
        private void HandleEvent(IAggregateRoot aggregateRoot, IDomainEvent evnt)
        {
            var handler = _eventHandlerProvider.GetInternalEventHandler(aggregateRoot.GetType(), evnt.GetType());
            if (handler == null)
            {
                throw new ENodeException("Could not find event handler for [{0}] of [{1}]", evnt.GetType().FullName, aggregateRoot.GetType().FullName);
            }

            handler(aggregateRoot, evnt);
        }
        private void PublishEvents(IAggregateRoot instance, IDomainNotification snapshotChange)
        {
            foreach (var evt in instance.UncommittedEvents.ToList())
            {
                var modelChange = NotificationExtensions.CreateNotification(instance.GetType(), evt);
                this.changes.OnNext(modelChange);
            }

            if (snapshotChange != null)
            {
                this.changes.OnNext(snapshotChange);
            }
        }
        private EventStream CreateEventStream(IAggregateRoot aggregateRoot, ICommand command)
        {
            var uncommittedEvents = aggregateRoot.GetUncommittedEvents().ToList();
            aggregateRoot.ClearUncommittedEvents();

            var aggregateRootTypeCode = _aggregateRootTypeProvider.GetTypeCode(aggregateRoot.GetType());

            foreach (var evnt in uncommittedEvents)
            {
                evnt.Version = aggregateRoot.Version + 1;
            }
            return new EventStream(
                command.Id,
                aggregateRoot.UniqueId,
                aggregateRootTypeCode,
                aggregateRoot.Version + 1,
                DateTime.Now,
                uncommittedEvents);
        }
		public ConcurrencyException(IAggregateRoot root, IDomainEvent conflictEvent)
			: base(string.Format("Expected version of {0}({1}) to be {2} but got {3}."
			, root.GetType().Name, root.Id, root.Version, conflictEvent.Version))
		{
		}
Exemple #43
0
 ///<summary>
 /// 将一个FisObject注册为Added
 ///</summary>
 ///<param name="entity">fisobject</param>
 ///<param name="repository">该FisObject类型的Repository对象</param>
 public void RegisterAdded(IAggregateRoot entity, IUnitOfWorkRepository repository)
 {
     if (!this._added.ContainsKey(entity))
     {
         logger.DebugFormat(MsgRegisterAdded, entity.GetType(), entity.Key);
         this._added.Add(entity, repository);
         _execSeq.Add(entity);
     }
 }