示例#1
0
 /// <summary>
 /// Persist the provided <paramref name="eventData"/> into SQL Server.
 /// </summary>
 /// <param name="eventData">The <see cref="EventData"/> to persist.</param>
 protected override void PersistEvent(EventData eventData)
 {
     using (SqlEventStoreDataContext dbDataContext = CreateDbDataContext(eventData.AggregateId.Substring(0, eventData.AggregateId.IndexOf("/", StringComparison.InvariantCultureIgnoreCase))))
     {
         Add(dbDataContext, eventData);
     }
 }
示例#2
0
        /// <summary>
        /// Get all <see cref="IEvent{TAuthenticationToken}"/> instances for the given <paramref name="correlationId"/>.
        /// </summary>
        /// <param name="correlationId">The <see cref="IMessage.CorrelationId"/> of the <see cref="IEvent{TAuthenticationToken}"/> instances to retrieve.</param>
        public override IEnumerable <EventData> Get(Guid correlationId)
        {
            using (SqlEventStoreDataContext dbDataContext = CreateDbDataContext())
            {
                string commandTimeoutValue;
                int    commandTimeout;
                bool   found = ConfigurationManager.TryGetSetting(SqlEventStoreGetByCorrelationIdCommandTimeout, out commandTimeoutValue);
                if (found && int.TryParse(commandTimeoutValue, out commandTimeout))
                {
#if NET40
                    // Get the ObjectContext related to this DbContext
                    var objectContext = (dbDataContext as IObjectContextAdapter).ObjectContext;

                    // Sets the command timeout for all the commands
                    objectContext.CommandTimeout = commandTimeout;
#else
                    dbDataContext.Database.SetCommandTimeout(commandTimeout);
#endif
                }

                IEnumerable <EventData> query = GetEventStoreTable(dbDataContext)
                                                .AsQueryable()
                                                .Where(eventData => eventData.CorrelationId == correlationId)
                                                .OrderBy(eventData => eventData.Timestamp);

                return(query.ToList());
            }
        }
示例#3
0
        /// <summary>
        /// Persist the provided <paramref name="eventData"/> into each SQL Server in <see cref="WritableConnectionStrings"/>.
        /// A single <see cref="TransactionScope"/> wraps all SQL servers, so all must complete successfully, or they will ALL roll back.
        /// </summary>
        /// <param name="eventData">The <see cref="EventData"/> to persist.</param>
        protected override void PersistEvent(EventData eventData)
        {
            try
            {
                using (TransactionScope scope = new TransactionScope())
                {
                    IList <Task> persistTasks = new List <Task>();
                    foreach (string connectionString in WritableConnectionStrings)
                    {
                        // Do not remove this variable copying or the parallel task stuff will bork.
                        var safeConnectionString            = connectionString;
                        DependentTransaction subTransaction = Transaction.Current.DependentClone(DependentCloneOption.BlockCommitUntilComplete);
                        Task task = Task.Factory.StartNewSafely
                                    (
                            (subTransactionObject) =>
                        {
                            var subTrx = (DependentTransaction)subTransactionObject;
                            //Pass the DependentTransaction to the scope, so that work done in the scope becomes part of the transaction passed to the worker thread
                            using (TransactionScope ts = new TransactionScope(subTrx))
                            {
                                using (SqlEventStoreDataContext dbDataContext = new SqlEventStoreDataContext(safeConnectionString))
                                    Add(dbDataContext, eventData);

                                //Call complete on the transaction scope
                                ts.Complete();
                            }

                            //Call complete on the dependent transaction
                            subTrx.Complete();
                        },
                            subTransaction
                                    );
                        persistTasks.Add(task);
                    }

                    bool anyFailed = Task.Factory.ContinueWhenAll(persistTasks.ToArray(), tasks =>
                    {
                        return(tasks.Any(task => task.IsFaulted));
                    }).Result;
                    if (anyFailed)
                    {
                        throw new AggregateException("Persisting data to the SQL event store failed. Check the logs for more details.");
                    }
                    scope.Complete();
                }
            }
            catch (TransactionException exception)
            {
                Logger.LogError("There was an issue with the SQL transaction persisting data to the SQL event store.", exception: exception);
                throw;
            }
            catch (Exception exception)
            {
                Logger.LogError("There was an issue persisting data to the SQL event store.", exception: exception);
                throw;
            }
        }
示例#4
0
        /// <summary>
        /// Gets a collection of <see cref="IEvent{TAuthenticationToken}"/> for the <see cref="IAggregateRoot{TAuthenticationToken}"/> of type <paramref name="aggregateRootType"/> with the ID matching the provided <paramref name="aggregateId"/> up to and including the provided <paramref name="version"/>.
        /// </summary>
        /// <param name="aggregateRootType"> <see cref="Type"/> of the <see cref="IAggregateRoot{TAuthenticationToken}"/> the <see cref="IEvent{TAuthenticationToken}"/> was raised in.</param>
        /// <param name="aggregateId">The <see cref="IAggregateRoot{TAuthenticationToken}.Id"/> of the <see cref="IAggregateRoot{TAuthenticationToken}"/>.</param>
        /// <param name="version">Load events up-to and including from this version</param>
        public override IEnumerable <IEvent <TAuthenticationToken> > GetToVersion(Type aggregateRootType, Guid aggregateId, int version)
        {
            string streamName = string.Format(CqrsEventStoreStreamNamePattern, aggregateRootType.FullName, aggregateId);

            using (SqlEventStoreDataContext dbDataContext = CreateDbDataContext(aggregateRootType.FullName))
            {
                IEnumerable <EventData> query = GetEventStoreTable(dbDataContext)
                                                .AsQueryable()
                                                .Where(eventData => eventData.AggregateId == streamName && eventData.Version <= version)
                                                .OrderByDescending(eventData => eventData.Version);

                return(query
                       .Select(EventDeserialiser.Deserialise)
                       .ToList());
            }
        }
示例#5
0
        /// <summary>
        /// Creates a new <see cref="DataContext"/> using connection string settings from <see cref="ConfigurationManager"/>.
        /// </summary>
        protected virtual DataContext CreateDbDataContext(string aggregateRootTypeName = null)
        {
            string connectionStringKey;
            string applicationKey;

            if (!ConfigurationManager.TryGetSetting(SqlEventStoreConnectionNameApplicationKey, out applicationKey) || string.IsNullOrEmpty(applicationKey))
            {
                if (!ConfigurationManager.TryGetSetting(SqlEventStoreDbFileOrServerOrConnectionApplicationKey, out connectionStringKey) || string.IsNullOrEmpty(connectionStringKey))
                {
                    if (!ConfigurationManager.TryGetSetting(SqlDataStore <Entity> .SqlDataStoreDbFileOrServerOrConnectionApplicationKey, out connectionStringKey) || string.IsNullOrEmpty(connectionStringKey))
                    {
                        throw new MissingApplicationSettingForConnectionStringException(SqlEventStoreConnectionNameApplicationKey);
                    }
                }
            }
            else
            {
                try
                {
                    connectionStringKey = System.Configuration.ConfigurationManager.ConnectionStrings[applicationKey].ConnectionString;
                }
                catch (NullReferenceException exception)
                {
                    throw new MissingConnectionStringException(applicationKey, exception);
                }
            }

            string tableName;

            if (!string.IsNullOrWhiteSpace(aggregateRootTypeName) && ConfigurationManager.TryGetSetting(string.Format(SqlEventStoreTableNameApplicationKeyPattern, aggregateRootTypeName), out tableName) && !string.IsNullOrEmpty(tableName))
            {
                bool autoname;
                if (bool.TryParse(tableName, out autoname))
                {
                    if (autoname)
                    {
                        return(SqlEventStoreDataContext.New <EventData>(aggregateRootTypeName.Replace(".", "_"), connectionStringKey));
                    }
                }
                else
                {
                    return(SqlEventStoreDataContext.New <EventData>(tableName, connectionStringKey));
                }
            }

            return(new SqlEventStoreDataContext(connectionStringKey));
        }
示例#6
0
        /// <summary>
        /// Get the latest <see cref="Snapshot"/> from storage.
        /// </summary>
        /// <returns>The most recent <see cref="Snapshot"/> of</returns>
        protected override Snapshot Get(Type aggregateRootType, string streamName)
        {
            using (SqlEventStoreDataContext dbDataContext = CreateDbDataContext(aggregateRootType.FullName))
            {
                EventData query = GetEventStoreSnapshotTable(dbDataContext)
                                  .AsQueryable()
                                  .Where(snapshot => snapshot.AggregateId == streamName)
                                  .OrderByDescending(eventData => eventData.Version)
                                  .Take(1)
                                  .SingleOrDefault();

                if (query == null)
                {
                    return(null);
                }
                return(EventDeserialiser.Deserialise(query));
            }
        }
示例#7
0
 /// <summary>
 /// Persist the provided <paramref name="data"/> into SQL Server using the provided <paramref name="dbDataContext"/>.
 /// </summary>
 protected virtual void Add(SqlEventStoreDataContext dbDataContext, EventData data)
 {
     Logger.LogDebug("Adding data to the SQL eventstore database", "SqlEventStore\\Add");
     try
     {
         DateTime start = DateTime.Now;
         GetEventStoreTable(dbDataContext).Add(data);
         dbDataContext.SaveChanges();
         DateTime end = DateTime.Now;
         Logger.LogDebug(string.Format("Adding data in the SQL eventstore database took {0}.", end - start), "SqlEventStore\\Add");
     }
     catch (Exception exception)
     {
         Logger.LogError("There was an issue persisting data to the SQL event store.", exception: exception);
         throw;
     }
     finally
     {
         Logger.LogDebug("Adding data to the SQL eventstore database... Done", "SqlEventStore\\Add");
     }
 }
示例#8
0
        /// <summary>
        /// Creates a new <see cref="DataContext"/> using connection string settings from ConfigurationManager.
        /// </summary>
        protected virtual DataContext CreateDbDataContext(string aggregateRootTypeName = null)
        {
            string connectionStringKey;
            string applicationKey;

            if (!ConfigurationManager.TryGetSetting(SqlSnapshotStoreConnectionNameApplicationKey, out applicationKey) || string.IsNullOrEmpty(applicationKey))
            {
                throw new MissingApplicationSettingForConnectionStringException(SqlSnapshotStoreConnectionNameApplicationKey);
            }
            ConnectionStringSettings connectionString = System.Configuration.ConfigurationManager.ConnectionStrings[applicationKey];

            if (connectionString == null)
            {
                throw new MissingConnectionStringException(applicationKey);
            }
            connectionStringKey = connectionString.ConnectionString;

            string tableName;

            if (!string.IsNullOrWhiteSpace(aggregateRootTypeName) && ConfigurationManager.TryGetSetting(string.Format(SqlSnapshotStoreTableNameApplicationKeyPattern, aggregateRootTypeName), out tableName) && !string.IsNullOrEmpty(tableName))
            {
                bool autoname;
                if (bool.TryParse(tableName, out autoname))
                {
                    if (autoname)
                    {
                        return(SqlEventStoreDataContext.New <EventData>(aggregateRootTypeName.Replace(".", "_"), connectionStringKey));
                    }
                }
                else
                {
                    return(SqlEventStoreDataContext.New <EventData>(tableName, connectionStringKey));
                }
            }

            return(SqlEventStoreDataContext.New <EventData>("Snapshots", connectionStringKey));
        }
示例#9
0
        /// <summary>
        /// Creates a new <see cref="DbContext"/> using connection string settings from <see cref="ConfigurationManager"/>.
        /// </summary>
        protected virtual SqlEventStoreDataContext CreateDbDataContext(string aggregateRootTypeName = null)
        {
            string connectionStringKey = ConfigurationManager.GetConnectionStringBySettingKey(SqlEventStoreConnectionNameApplicationKey, true, true);

            string tableName;

            if (!string.IsNullOrWhiteSpace(aggregateRootTypeName) && ConfigurationManager.TryGetSetting(string.Format(SqlEventStoreTableNameApplicationKeyPattern, aggregateRootTypeName), out tableName) && !string.IsNullOrEmpty(tableName))
            {
                bool autoname;
                if (bool.TryParse(tableName, out autoname))
                {
                    if (autoname)
                    {
                        return(SqlEventStoreDataContext.New(aggregateRootTypeName.Replace(".", "_"), connectionStringKey));
                    }
                }
                else
                {
                    return(SqlEventStoreDataContext.New(tableName, connectionStringKey));
                }
            }

            return(new SqlEventStoreDataContext(connectionStringKey));
        }
示例#10
0
 /// <summary>
 /// Saves the provided <paramref name="snapshot"/> into storage.
 /// </summary>
 /// <param name="snapshot">the <see cref="Snapshot"/> to save and store.</param>
 public override void Save(Snapshot snapshot)
 {
     using (SqlEventStoreDataContext dbDataContext = CreateDbDataContext(snapshot.GetType().Name))
         Add(dbDataContext, snapshot);
 }
示例#11
0
 /// <summary>
 /// Gets the <see cref="DbSet{TEntity}"/> of <see cref="Snapshot"/>.
 /// </summary>
 /// <param name="dbDataContext">The <see cref="DbContext"/> to use.</param>
 protected virtual DbSet <EventData> GetEventStoreSnapshotTable(SqlEventStoreDataContext dbDataContext)
 {
     // Get a typed table to run queries.
     return(dbDataContext.Set <EventData>());
 }