public void ShouldCacheEventsBetweenInstancesTransaction()
        {
            using (var dbManager = new TemporaryLocalDbManager(ConfigurationManager.ConnectionStrings["MasterDb"].ConnectionString))
            {
                var connectionString = dbManager.CreateOrGetLocalDb("SqlServerEventStoreTest_EventStore2");
                var something        = new SqlServerEventStore(connectionString, new SingleThreadUseGuard());

                var user = new User();
                user.Register("*****@*****.**", "password", Guid.NewGuid());
                var stored = (IEventStored)user;

                using (var tran = new TransactionScope())
                {
                    something.SaveEvents(stored.GetChanges());
                    something.GetAggregateHistory(user.Id);
                    Assert.That(something.GetAggregateHistory(user.Id), Is.Not.Empty);
                    tran.Complete();
                }

                something = new SqlServerEventStore(connectionString, new SingleThreadUseGuard());
                var firstRead = something.GetAggregateHistory(user.Id).Single();

                something = new SqlServerEventStore(connectionString, new SingleThreadUseGuard());
                var secondRead = something.GetAggregateHistory(user.Id).Single();

                Assert.That(firstRead, Is.SameAs(secondRead));
            }
        }
        public void TrySaveMultipleEvents()
        {
            // arrange
            var eventStore = new SqlServerEventStore(this.ConnectionString);
            var streamId   = Guid.NewGuid();
            var events     = new[]
            {
                new Event {
                    Id = 1, Value = "One"
                },
                new Event {
                    Id = 2, Value = "Two"
                },
            };

            string commitState;
            string actualCommitState;

            // act
            eventStore.CommitStream(streamId, events, Guid.NewGuid(), null, out commitState);
            var actualEvents = eventStore.GetStream(streamId, 0, out actualCommitState);

            // assert
            actualEvents.Count().Should().Be(2);
            actualEvents.First().Should().BeOfType <Event>();
            actualEvents.Last().Should().BeOfType <Event>();
            actualEvents.Cast <Event>().First().ShouldBeEquivalentTo(events[0]);
            actualEvents.Cast <Event>().Last().ShouldBeEquivalentTo(events[1]);
            actualCommitState.Should().Be(commitState);
        }
        public void TrySaveEventsForMultipleStreams()
        {
            // arrange
            var eventStore = new SqlServerEventStore(this.ConnectionString);
            var stream1Id  = Guid.NewGuid();
            var stream2Id  = Guid.NewGuid();
            var events1    = new[] { new Event {
                                         Id = 1, Value = "One"
                                     } };
            var events2 = new[] { new Event {
                                      Id = 2, Value = "Two"
                                  } };

            string stream1CommitState;
            string stream2CommitState;
            string actualStream1CommitState;
            string actualStream2CommitState;

            // act
            eventStore.CommitStream(stream1Id, events1, Guid.NewGuid(), null, out stream1CommitState);
            eventStore.CommitStream(stream2Id, events2, Guid.NewGuid(), null, out stream2CommitState);
            var stream1Events = eventStore.GetStream(stream1Id, 0, out actualStream1CommitState);
            var stream2Events = eventStore.GetStream(stream2Id, 0, out actualStream2CommitState);

            // assert
            stream1Events.Count().Should().Be(1);
            stream1Events.Single().Should().BeOfType <Event>();
            stream1Events.Cast <Event>().Single().ShouldBeEquivalentTo(events1[0]);
            actualStream1CommitState.Should().Be(stream1CommitState);
            stream2Events.Count().Should().Be(1);
            stream2Events.Single().Should().BeOfType <Event>();
            stream2Events.Cast <Event>().Single().ShouldBeEquivalentTo(events2[0]);
            actualStream2CommitState.Should().Be(stream2CommitState);
        }
        public void ExpectServerSideConcurrencyException()
        {
            // arrange
            var eventStore = new SqlServerEventStore(this.ConnectionString);
            var streamId   = Guid.NewGuid();
            var events     = new[] { new Event {
                                         Id = 1, Value = "One"
                                     } };

            string commitState;

            using (new TransactionScope(TransactionScopeOption.RequiresNew))
                using (var connection = new SqlConnection(this.ConnectionString))
                    using (var command = connection.CreateCommand())
                    {
                        command.CommandType = CommandType.Text;
                        command.CommandText = @"EXEC sp_getapplock @Resource = @StreamId, @LockMode = 'Exclusive', @LockTimeout = 1000;";
                        command.Parameters.Add("@StreamId", SqlDbType.UniqueIdentifier).Value = streamId;

                        // NOTE (Cameron): This will cause SQL Server to acquire the same application lock as the commit attempt below.
                        connection.Open();
                        command.ExecuteNonQuery();

                        // act
                        Action action = () => eventStore.CommitStream(streamId, events, Guid.NewGuid(), null, out commitState);

                        // assert
                        action.ShouldThrow <ConcurrencyException>();
                    }
        }
        public void TrySaveEventsInMultipleCommits()
        {
            // arrange
            var eventStore = new SqlServerEventStore(this.ConnectionString);
            var streamId   = Guid.NewGuid();
            var events1    = new[] { new Event {
                                         Id = 1, Value = "One"
                                     } };
            var events2 = new[] { new Event {
                                      Id = 2, Value = "Two"
                                  } };

            string firstCommitState;
            string secondCommitState;
            string actualCommitState;

            // act
            eventStore.CommitStream(streamId, events1, Guid.NewGuid(), null, out firstCommitState);
            eventStore.CommitStream(streamId, events2, Guid.NewGuid(), firstCommitState, out secondCommitState);
            var actualEvents = eventStore.GetStream(streamId, 0, out actualCommitState);

            // assert
            actualEvents.Count().Should().Be(2);
            actualEvents.First().Should().BeOfType <Event>();
            actualEvents.Last().Should().BeOfType <Event>();
            actualEvents.Cast <Event>().First().ShouldBeEquivalentTo(events1[0]);
            actualEvents.Cast <Event>().Last().ShouldBeEquivalentTo(events2[0]);
            actualCommitState.Should().Be(secondCommitState);
        }
        public void SqlServerEventStore_RetrieveEvents_PlainEvent_Should_Work()
        {
            var eventStore = new SqlServerEventStore(this.Settings, this.EventDispatcher);

            var aggId = Guid.NewGuid();

            var events = new[]
            {
                new PlainEvent(aggId, PlainEvent.TestEnum.Nope),
                new PlainEvent(aggId, null),
                new PlainEvent(Guid.NewGuid(), null),
                new PlainEvent(aggId, PlainEvent.TestEnum.Ok),
            };

            var eventsCount = events.Count(e => e.MyAggId == aggId);

            foreach (var @event in events)
            {
                eventStore.Save(@event);
            }

            var eventMapping = new EventMapping {
                AggregateIdPropertyName = nameof(PlainEvent.MyAggId), EventType = typeof(PlainEvent)
            };

            var eventDescriptors = new[] { eventMapping };

            var savedEvents = eventStore.RetrieveEvents(aggId, DateTime.Now, eventDescriptors, timelineId: null);

            Assert.NotNull(savedEvents);
            Assert.NotEmpty(savedEvents);
            Assert.True(savedEvents.All(e => e is PlainEvent));

            Assert.Equal(eventsCount, savedEvents.Count());
        }
        public void SqlServerEventStore_Save_And_Find_Should_Retrieve_EnumEvent_Without_Throwing_When_NullableConfirm_Is_Not_Null()
        {
            var enumEvent = new EnumEvent(EnumEvent.TestEnum.Yes, nullableConfirm: EnumEvent.TestEnum.No);

            var eventId = enumEvent.Id;

            var eventStore = new SqlServerEventStore(Config.ConnectionString, this.EventDispatcher);

            eventStore.Save(enumEvent);

            System.Threading.Thread.Sleep(1000);

            var events = eventStore.Find <EnumEvent>(e => e.Id == eventId).ToArray();

            Assert.NotNull(events);
            Assert.Single(events);

            var @event = events[0];

            Assert.Equal(enumEvent.Id, @event.Id);
            Assert.Equal(enumEvent.TimelineId, @event.TimelineId);
            Assert.Equal(enumEvent.TimeStamp.ToLongDateString(), @event.TimeStamp.ToLongDateString());
            Assert.Equal(enumEvent.RequiredConfirm, @event.RequiredConfirm);
            Assert.Equal(enumEvent.NullableConfirm, @event.NullableConfirm);
            Assert.NotNull(@event.NullableConfirm);
        }
        public async Task Replays_All_Events_In_Order()
        {
            var store = new SqlServerEventStore(_conStr);

            DeleteEventsTable();

            var eventsReceived = new List <IEvent>();

            store.EventHandler = e =>
            {
                eventsReceived.Add(e);
                return(Task.CompletedTask);
            };

            // Raise some events
            await store.RaiseEventAsync(new TestEvent("Hello, World!"));

            await store.RaiseEventAsync(new TestEvent("Hello, Bob!"));

            await store.RaiseEventAsync(new TestEvent("Hello, Dave!"));

            // Pretend we haven't seen them yet
            eventsReceived.Clear();

            // Replay and check they are correct
            await store.ReplayAllEvents();

            eventsReceived[0].Stream.ShouldBe("test-stream");
            ((TestEvent)eventsReceived[0]).TestValue.ShouldBe("Hello, World!");
            eventsReceived[1].Stream.ShouldBe("test-stream");
            ((TestEvent)eventsReceived[1]).TestValue.ShouldBe("Hello, Bob!");
            eventsReceived[2].Stream.ShouldBe("test-stream");
            ((TestEvent)eventsReceived[2]).TestValue.ShouldBe("Hello, Dave!");
        }
Example #9
0
        public void TryGetMultipleBatchesFromEventStoreWithManyEvents()
        {
            // arrange
            var eventDispatcherEventStore = new SqlServerEventDispatcherEventStore(this.ConnectionString);
            var eventStore = new SqlServerEventStore(this.ConnectionString);
            var streamId   = Guid.NewGuid();
            var events     = new[]
            {
                new Event {
                    Id = 4, Value = "Four"
                },
                new Event {
                    Id = 5, Value = "Five"
                },
                new Event {
                    Id = 6, Value = "Six"
                },
            };

            string commitState;

            eventStore.CommitStream(streamId, events, Guid.NewGuid(), null, out commitState);

            // act
            var firstBatch  = eventDispatcherEventStore.GetNextUndispatchedEventsBatch(Guid.Empty, 2);
            var secondBatch = eventDispatcherEventStore.GetNextUndispatchedEventsBatch(Guid.Empty, 2);

            // assert
            firstBatch.Should().NotBeNull();
            firstBatch.Events.Should().Contain(@event => @event.Payload.As <Event>().Id == 4 && @event.Payload.As <Event>().Value == "Four");
            firstBatch.Events.Should().Contain(@event => @event.Payload.As <Event>().Id == 5 && @event.Payload.As <Event>().Value == "Five");
            secondBatch.Should().NotBeNull();
            secondBatch.Events.Should().ContainSingle(@event => @event.Payload.As <Event>().Id == 6 && @event.Payload.As <Event>().Value == "Six");
        }
        public void LoadEventsTest()
        {
            var aggregateRootId = Guid.NewGuid();
            var employee        = new Employee(aggregateRootId);

            var event1 = new NameChangedEvent("daxnet");
            var event2 = new TitleChangedEvent("title");
            var event3 = new RegisteredEvent();

            event1.AttachTo(employee);
            event2.AttachTo(employee);
            event3.AttachTo(employee);

            var storeConfig       = new AdoNetEventStoreConfiguration(SQLServerFixture.ConnectionString, new GuidKeyGenerator());
            var payloadSerializer = new ObjectJsonSerializer();
            var store             = new SqlServerEventStore(storeConfig, payloadSerializer);

            store.Save(new List <DomainEvent>
            {
                event1,
                event2,
                event3
            });

            var events = store.Load <Guid>(typeof(Employee).AssemblyQualifiedName, aggregateRootId);

            Assert.Equal(3, events.Count());
        }
Example #11
0
        public void TryGetBatchTwiceFromEventStoreWithSingleEventAndDifferentDispatchers()
        {
            // arrange
            var eventDispatcherEventStore = new SqlServerEventDispatcherEventStore(this.ConnectionString);
            var eventStore = new SqlServerEventStore(this.ConnectionString);
            var streamId   = Guid.NewGuid();
            var events     = new[]
            {
                new Event {
                    Id = 3, Value = "Three"
                },
            };

            string commitState;

            eventStore.CommitStream(streamId, events, Guid.NewGuid(), null, out commitState);

            // act
            var firstBatch  = eventDispatcherEventStore.GetNextUndispatchedEventsBatch(Guid.NewGuid(), 50);
            var secondBatch = eventDispatcherEventStore.GetNextUndispatchedEventsBatch(Guid.NewGuid(), 50);

            // assert
            firstBatch.Should().NotBeNull();
            firstBatch.Events.Should().ContainSingle(@event => @event.Payload.As <Event>().Id == 3 && @event.Payload.As <Event>().Value == "Three");
            secondBatch.Should().NotBeNull();
            secondBatch.Events.Should().ContainSingle(@event => @event.Payload.As <Event>().Id == 3 && @event.Payload.As <Event>().Value == "Three");
        }
        public void SqlServerEventStore_Find_ComplexEvent_Should_Work()
        {
            var eventStore = new SqlServerEventStore(this.Settings, this.EventDispatcher);

            var events = eventStore.Find <ComplexEvent>(e => e.N > 0).ToArray();

            Assert.NotNull(events);
            Assert.NotEmpty(events);
        }
        public void SqlServerEventStore_Find_PlainEvent_Should_Work()
        {
            var eventStore = new SqlServerEventStore(this.Settings, this.EventDispatcher);

            var events = eventStore.Find <PlainEvent>(e => e.MyAggId != Guid.Empty).ToArray();

            Assert.NotNull(events);
            Assert.NotEmpty(events);
        }
        public void SqlServerEventStore_Find_NotMappedEvent_Should_Return_Empty_Collection_If_Table_Does_Not_Exist()
        {
            var eventStore = new SqlServerEventStore(this.Settings, this.EventDispatcher);

            var events = eventStore.Find <NotMappedEvent>(p => p.Id == Guid.Empty);

            Assert.NotNull(events);
            Assert.Empty(events);
        }
        public void Connecting_to_undefined_database_name_throws_exception()
        {
            var store = new SqlServerEventStore("InvalidConnnectionName", _logger);
            var user  = new User();

            user.Register();
            user.ChangePassword("password");
            Assert.Throws <InvalidOperationException>(
                () => store.Save <User>(user.Id.ToString(), EventStreamVersion.NoStream, user.GetUncommittedEvents()));
        }
Example #16
0
        public void Connecting_to_SqlClient_does_not_throw_exception()
        {
            var store = new SqlServerEventStore("SqlClientConnection", _logger);
            var user  = new User();

            user.Register();
            user.ChangePassword("password");
            Assert.DoesNotThrow(
                () => store.Save <User>(user.Id.ToString(), EntityVersion.New, user.GetUncommittedEvents()));
        }
Example #17
0
        public void Connecting_to_non_SqlClient_throws_exception()
        {
            var store = new SqlServerEventStore("NonSqlClientConnection", _logger);
            var user  = new User();

            user.Register();
            user.ChangePassword("password");
            Assert.Throws <InvalidOperationException>(
                () => store.Save <User>(user.Id.ToString(), EntityVersion.New, user.GetUncommittedEvents()));
        }
        public void SqlServerEventStore_Save_PlainEvent_Should_Work()
        {
            var eventStore = new SqlServerEventStore(this.Settings, this.EventDispatcher);

            var guid = Guid.NewGuid();

            var plainEvent = new PlainEvent(guid, PlainEvent.TestEnum.Nope);

            var exception = Record.Exception(() => eventStore.Save(plainEvent));

            Assert.Null(exception);
        }
        public void SqlServerEventStore_Save_ComplexEvent_Should_Work()
        {
            var eventStore = new SqlServerEventStore(this.Settings, this.EventDispatcher);

            var stringList = new List <string> {
                "Hello", "Memento"
            };

            var myProp = new ComplexEvent.InternalProp(stringList);

            var complexEvent = new ComplexEvent(Guid.NewGuid(), Environment.TickCount, "PROV@", myProp, byte.MaxValue);

            var exception = Record.Exception(() => eventStore.Save(complexEvent));

            Assert.Null(exception);
        }
        public async Task Raises_And_Replays_Single_Event()
        {
            var store = new SqlServerEventStore(_conStr);

            DeleteEventsTable();

            IEvent eventReceived = null;

            store.EventHandler = e =>
            {
                eventReceived = e;
                return(Task.CompletedTask);
            };

            await store.RaiseEventAsync(new TestEvent("Hello, World!"));

            eventReceived.Stream.ShouldBe("test-stream");
            ((TestEvent)eventReceived).TestValue.ShouldBe("Hello, World!");
        }
        public async Task Subscribes_To_Events_From_Outside_Application()
        {
            var store = new SqlServerEventStore(_conStr);

            DeleteEventsTable();

            IEvent eventReceived = null;

            store.EventHandler = e =>
            {
                eventReceived = e;
                return(Task.CompletedTask);
            };

            // Manually add an event
            using (var conn = new SqlConnection(_conStr))
            {
                conn.Open();

                var createTable = new SqlCommand(
                    "If not exists (select name from sysobjects where name = 'events') " +
                    "    CREATE TABLE events(streamName nvarchar(max), eventName nvarchar(max), payload nvarchar(max), created datetime2)",
                    conn);

                await createTable.ExecuteNonQueryAsync().ConfigureAwait(false);

                var command = new SqlCommand(
                    "insert into events (streamName, eventName, payload, created) values (@0,@1,@2,@3)",
                    conn);

                command.Parameters.AddWithValue("@0", "other-app-stream");
                command.Parameters.AddWithValue("@1", typeof(TestEvent).AssemblyQualifiedName);
                command.Parameters.AddWithValue("@2", JsonConvert.SerializeObject(new TestEvent("This is a test")));
                command.Parameters.AddWithValue("@3", DateTime.Now);

                await command.ExecuteScalarAsync().ConfigureAwait(false);
            }

            // Check we received it
            eventReceived.Stream.ShouldBe("other-app-stream");
            ((TestEvent)eventReceived).TestValue.ShouldBe("Hello, World!");
        }
        public void ShouldNotCacheEventsSavedDuringFailedTransactionEvenIfReadDuringSameTransaction()
        {
            using (var dbManager = new TemporaryLocalDbManager(ConfigurationManager.ConnectionStrings["MasterDb"].ConnectionString))
            {
                var connectionString = dbManager.CreateOrGetLocalDb("SqlServerEventStoreTest_EventStore1");
                var something        = new SqlServerEventStore(connectionString, new SingleThreadUseGuard());
                something.ResetDB(); //Sometimes the test would fail on the last line with information that the table was missing. Probably because the table was created during the aborted transaction. I'm hoping this will fix it.

                var user = new User();
                user.Register("*****@*****.**", "password", Guid.NewGuid());

                using (new TransactionScope())
                {
                    something.SaveEvents(((IEventStored)user).GetChanges());
                    something.GetAggregateHistory(user.Id);
                    Assert.That(something.GetAggregateHistory(user.Id), Is.Not.Empty);
                }

                Assert.That(something.GetAggregateHistory(user.Id), Is.Empty);
            }
        }
        public void SqlServerEventStore_RetrieveEvents_ComplexEvent_Should_Work()
        {
            var eventStore = new SqlServerEventStore(this.Settings, this.EventDispatcher);

            var complexId = Guid.NewGuid();

            var events = new[]
            {
                new ComplexEvent(complexId, Environment.TickCount, "PROV@", new ComplexEvent.InternalProp(new List <string> {
                    "Hello", "Memento"
                }), byte.MaxValue),
                new ComplexEvent(complexId, 10000, "test titolo", new ComplexEvent.InternalProp(new List <string>()), byte.MinValue),
                new ComplexEvent(Guid.NewGuid(), 8787878, null, null, 0),
                new ComplexEvent(complexId, 12345, string.Empty, new ComplexEvent.InternalProp(new List <string> {
                    "test"
                }), 128),
            };

            var eventsCount = events.Count(e => e.ComplexId == complexId);

            foreach (var @event in events)
            {
                eventStore.Save(@event);
            }

            var eventMapping = new EventMapping {
                AggregateIdPropertyName = nameof(ComplexEvent.ComplexId), EventType = typeof(ComplexEvent)
            };

            var eventDescriptors = new[] { eventMapping };

            var savedEvents = eventStore.RetrieveEvents(complexId, DateTime.Now, eventDescriptors, timelineId: null);

            Assert.NotNull(savedEvents);
            Assert.NotEmpty(savedEvents);
            Assert.True(savedEvents.All(e => e is ComplexEvent));

            Assert.Equal(eventsCount, savedEvents.Count());
        }
Example #24
0
        public void ExpectClientSideConcurrencyException()
        {
            // arrange
            var eventStore = new SqlServerEventStore(this.ConnectionString);
            var streamId   = Guid.NewGuid();
            var events1    = new[] { new Event {
                                         Id = 1, Value = "One"
                                     } };
            var events2 = new[] { new Event {
                                      Id = 1, Value = "AnotherOne"
                                  } };

            string commitState;

            eventStore.CommitStream(streamId, events1, Guid.NewGuid(), null, out commitState);

            // act
            Action action = () => eventStore.CommitStream(streamId, events2, Guid.NewGuid(), null, out commitState);

            // assert
            action.ShouldThrow <ConcurrencyException>();
        }
        public void SqlServerEventStore_Find_PlainEvent_Should_Retrieve_Previously_Saved_Event()
        {
            var myAggId = Guid.NewGuid();

            var plainEvent = new PlainEvent(myAggId, null);

            var eventStore = new SqlServerEventStore(this.Settings, this.EventDispatcher);

            eventStore.Save(plainEvent);

            var events = eventStore.Find <PlainEvent>(e => e.MyAggId == myAggId).ToArray();

            Assert.NotNull(events);
            Assert.Single(events);

            var @event = events[0];

            Assert.Equal(myAggId, @event.MyAggId);
            Assert.Equal(plainEvent.Id, @event.Id);
            Assert.Equal(plainEvent.TimeStamp.ToLongDateString(), @event.TimeStamp.ToLongDateString());
            Assert.Null(@event.TimelineId);
        }
Example #26
0
        public void TryGetBatchFromEventStoreWithSingleEvent()
        {
            // arrange
            var eventDispatcherEventStore = new SqlServerEventDispatcherEventStore(this.ConnectionString);
            var eventStore = new SqlServerEventStore(this.ConnectionString);
            var streamId   = Guid.NewGuid();
            var events     = new[]
            {
                new Event {
                    Id = 1, Value = "One"
                },
            };

            string commitState;

            eventStore.CommitStream(streamId, events, Guid.NewGuid(), null, out commitState);

            // act
            var batch = eventDispatcherEventStore.GetNextUndispatchedEventsBatch(Guid.Empty, 50);

            // assert
            batch.Should().NotBeNull();
            batch.Events.Should().ContainSingle(@event => @event.Payload.As <Event>().Id == 1 && @event.Payload.As <Event>().Value == "One");
        }
        public async Task GIVEN_events_to_save_with_existing_concurrency_WHEN_executing_calling_store_methods_THEN_throws_ConcurrencyException()
        {
            var eventStore = new SqlServerEventStore <string>(Settings, SqlStatementsLoader, new SqlServerConnectionFactory(), MockEventDataSerializer.Object);

            await ExecuteConcurrencyCheckTest(eventStore, eventStore);
        }
        public void SqlServerEventStore_Ctor_Should_Not_Return_Null_Instance()
        {
            var eventStore = new SqlServerEventStore(this.Settings, this.EventDispatcher);

            Assert.NotNull(eventStore);
        }
 public void Does_not_call_db_in_constructor()
 {
     var eventStore = new SqlServerEventStore("SomeStringThatDoesNotPointToARealSqlServer", new SingleThreadUseGuard());
 }
        public async Task GIVEN_events_to_save_WHEN_executing_calling_store_methods_THEN_initializes_event_store_AND_saves_events_AND_gets_events_from_event_store()
        {
            var eventStore = new SqlServerEventStore <string>(Settings, SqlStatementsLoader, new SqlServerConnectionFactory(), MockEventDataSerializer.Object);

            await ExecuteTest(eventStore, eventStore);
        }