예제 #1
0
        public void Store(Guid aggregateId, long aggregateVersion, EventBase[] events)
        {
            var currentVersion = aggregateVersion;
            var expectedInitialVersion = currentVersion - events.Count();
            var streamId = aggregateId;

            var connectionString = _dataAccessConfiguration.EventStoreConnectionString;
            var serializedEvents = events.Select(x => new Tuple<string, string>(
                x.GetType().FullName + "," + x.GetType().Assembly.GetName(), JsonConvert.SerializeObject(x, _serializerSettings)));

            using (var t = new TransactionScope(TransactionScopeOption.Required,
                new TransactionOptions { IsolationLevel = IsolationLevel.Serializable }))
            {
                using (var con = new SqlConnection(connectionString))
                {
                    con.Open();

                    const string commandText = "SELECT TOP 1 CurrentSequence " +
                        "FROM Streams WITH (UPDLOCK) WHERE StreamId = @StreamId;";

                    long? existingSequence;
                    using (var command = new SqlCommand(commandText, con))
                    {
                        command.Parameters.AddWithValue("StreamId", streamId);
                        var current = command.ExecuteScalar();
                        existingSequence = current == null ? (long?)null : (long)current;

                        if (existingSequence != null && ((long)existingSequence) != expectedInitialVersion)
                            throw new ConcurrencyException();
                    }

                    var nextVersion = InsertEventsAndReturnLastVersion(streamId, con, expectedInitialVersion, serializedEvents);

                    if (existingSequence == null)
                        StartNewSequence(streamId, nextVersion, con);
                    else
                        UpdateSequence(streamId, expectedInitialVersion, nextVersion, con);

                    t.Complete();
                }
            }

            _bus.Publish(events);
        }