/// <summary>
 /// This is a very special way to interact with an aggregate, it is the standard pattern
 /// where a command handler load an aggregate, invokes some methods on it then save.
 /// It can use cached instance of <see cref="IAggregateCachedRepository{TAggregate}"/> thus
 /// achieving really faster performances.
 /// </summary>
 /// <param name="id"></param>
 /// <param name="callback"></param>
 /// <param name="createIfNotExists"></param>
 protected void FindAndModify(EventStoreIdentity id, Action <TAggregate> callback, bool createIfNotExists = false)
 {
     if (JarvisFrameworkGlobalConfiguration.SingleAggregateRepositoryCacheEnabled)
     {
         //Lock is NEEDED because multiple thread cannot access the very same aggregate.
         lock (NamedLocker.Instance.GetLock(id.Id))
         {
             using (var repo = AggregateCachedRepositoryFactory.Create <TAggregate>(id))
             {
                 var aggregate = repo.Aggregate;
                 if (!createIfNotExists && aggregate.Version == 0)
                 {
                     throw new UninitializedAggregateException();
                 }
                 SetupContext(aggregate);
                 callback(aggregate);
                 repo.Save(_commitId, StoreCommandHeaders);
             }
         }
     }
     else
     {
         //This is the classic command execution, each execution reload the entity and stream.
         var aggregate = Repository.GetById <TAggregate>(id);
         if (!createIfNotExists && aggregate.Version == 0)
         {
             throw new UninitializedAggregateException();
         }
         SetupContext(aggregate);
         callback(aggregate);
         Repository.Save(aggregate, _commitId, StoreCommandHeaders);
     }
 }
示例#2
0
        /// <summary>
        /// This is a very special way to interact with an aggregate, it is the standard pattern
        /// where a command handler load an aggregate, invokes some methods on it then save.
        /// It can use cached instance of <see cref="IAggregateCachedRepository{TAggregate}"/> thus
        /// achieving really faster performances.
        /// </summary>
        /// <param name="id"></param>
        /// <param name="callback"></param>
        /// <param name="createIfNotExists"></param>
        protected virtual async Task FindAndModifyAsync(
            EventStoreIdentity id,
            Func <TAggregate, Task <RepositoryCommandHandlerCallbackReturnValue> > callback,
            bool createIfNotExists = false)
        {
            if (JarvisFrameworkGlobalConfiguration.SingleAggregateRepositoryCacheEnabled)
            {
                //Lock is NEEDED because multiple thread cannot access the very same aggregate.
                lock (NamedLocker.Instance.GetLock(id.Id))
                {
                    using (var repo = AggregateCachedRepositoryFactory.Create <TAggregate>(id))
                    {
                        var aggregate = repo.Aggregate;

                        if (!createIfNotExists && aggregate.Version == 0)
                        {
                            throw new UninitializedAggregateException();
                        }

                        CheckAggregateVersionForIfVersionEqualTo(repo.Aggregate);

                        //TODO: Waiting is not a perfect solution, but we cannot await inside a lock.
                        var callbackResult = callback(aggregate).Result;
                        if (!callbackResult.ShouldNotPersistAggregate)
                        {
                            //TODO: Waiting is not a perfect solution, but we cannot await inside a lock.
                            repo.SaveAsync(_commitId, StoreCommandHeaders).Wait();
                        }
                    }
                }
            }
            else
            {
                //This is the classic command execution, each execution reload the entity and stream.
                var aggregate = await Repository.GetByIdAsync <TAggregate>(id).ConfigureAwait(false);

                if (!createIfNotExists && aggregate.Version == 0)
                {
                    throw new UninitializedAggregateException();
                }

                CheckAggregateVersionForIfVersionEqualTo(aggregate);

                var callbackResult = await callback(aggregate).ConfigureAwait(false);

                if (!callbackResult.ShouldNotPersistAggregate)
                {
                    await Repository.SaveAsync(aggregate, _commitId.ToString(), StoreCommandHeaders).ConfigureAwait(false);
                }
            }
        }