public virtual async Task <T> GetByIdAsync <T>(Guid id) where T : AggregateRoot { T item = default(T); var isSnapshottable = typeof(ISnapshottable).IsAssignableFrom(typeof(T)); Snapshot.Snapshot snapshot = null; if ((isSnapshottable) && (SnapshotStorageProvider != null)) { snapshot = await SnapshotStorageProvider.GetSnapshotAsync(typeof(T), id); } if (snapshot != null) { item = ReflectionHelper.CreateInstance <T>(); ((ISnapshottable)item).ApplySnapshot(snapshot); var events = await EventStorageProvider.GetEventsAsync(typeof(T), id, snapshot.Version + 1, int.MaxValue); item.LoadsFromHistory(events); } else { var events = (await EventStorageProvider.GetEventsAsync(typeof(T), id, 0, int.MaxValue)).ToList(); if (!events.Any()) { return(item); } item = ReflectionHelper.CreateInstance <T>(); item.LoadsFromHistory(events); } return(item); }
private async Task CommitChanges(AggregateRoot aggregate) { var expectedVersion = aggregate.LastCommittedVersion; IEvent item = await EventStorageProvider.GetLastEventAsync(aggregate.GetType(), aggregate.Id); if ((item != null) && (expectedVersion == (int)AggregateRoot.StreamState.NoStream)) { throw new AggregateCreationException($"Aggregate {item.CorrelationId} can't be created as it already exists with version {item.TargetVersion + 1}"); } if ((item != null) && ((item.TargetVersion + 1) != expectedVersion)) { throw new ConcurrencyException($"Aggregate {item.CorrelationId} has been modified externally and has an updated state. Can't commit changes."); } var changesToCommit = aggregate.GetUncommittedChanges().ToList(); //perform pre commit actions foreach (var e in changesToCommit) { DoPreCommitTasks(e); } //CommitAsync events to storage provider await EventStorageProvider.CommitChangesAsync(aggregate); //Publish to event publisher asynchronously foreach (var e in changesToCommit) { await EventPublisher.PublishAsync(e); } //If the Aggregate implements snaphottable var snapshottable = aggregate as ISnapshottable; if ((snapshottable != null) && (SnapshotStorageProvider != null)) { //Every N events we save a snapshot if ((aggregate.CurrentVersion >= SnapshotStorageProvider.SnapshotFrequency) && ( (changesToCommit.Count >= SnapshotStorageProvider.SnapshotFrequency) || (aggregate.CurrentVersion % SnapshotStorageProvider.SnapshotFrequency < changesToCommit.Count) || (aggregate.CurrentVersion % SnapshotStorageProvider.SnapshotFrequency == 0) ) ) { await SnapshotStorageProvider.SaveSnapshotAsync(aggregate.GetType(), snapshottable.TakeSnapshot()); } } aggregate.MarkChangesAsCommitted(); }