public async Task AssertSideEffectsAsync(ExpectedSideEffects sideEffects)
        {
            if (this.tables.Count == 0)
            {
                throw new Exception("No snapshot found. Did you forget to take a snapshot?");
            }

            var stopwatch = Stopwatch.StartNew();

            if (object.ReferenceEquals(sideEffects, ExpectedSideEffects.TransactionAborted))
            {
                if (Transaction.Current.TransactionInformation.Status != TransactionStatus.Aborted)
                {
                    Assert.Fail("Transaction was not aborted.");
                }

                // We can't check anything else if the transaction is aborted.
                return;
            }

            using (var databaseContext = this.testDatabase.CreateContext())
            {
                databaseContext.Configuration.AutoDetectChangesEnabled = false;
                databaseContext.Configuration.LazyLoadingEnabled       = false;
                databaseContext.Configuration.ValidateOnSaveEnabled    = false;
                databaseContext.Configuration.ProxyCreationEnabled     = false;

                foreach (var table in this.tables)
                {
                    table.GetLatestFromDatabase(databaseContext);
                }
            }

            Trace.WriteLine(string.Format("Queried latest in {0}s", Math.Round(stopwatch.Elapsed.TotalSeconds, 2)));

            stopwatch = Stopwatch.StartNew();

            foreach (var table in this.tables)
            {
                this.AssertNoUnexpectedSideEffects(table.Snapshot, table.Database, sideEffects);
            }

            Trace.WriteLine(string.Format("Asserted no unexpected side effects in {0}s", Math.Round(stopwatch.Elapsed.TotalSeconds, 2)));

            stopwatch = Stopwatch.StartNew();

            var snapshot = this.tables.SelectMany(_ => _.Snapshot).ToList();
            var database = this.tables.SelectMany(_ => _.Database).ToList();

            this.AssertExpectedSideEffects(snapshot, database, sideEffects);

            Trace.WriteLine(string.Format("Asserted expected side effects in {0}s", Math.Round(stopwatch.Elapsed.TotalSeconds, 2)));
        }
        private void AssertExpectedSideEffects(IReadOnlyCollection <IIdentityEquatable> snapshot, IReadOnlyCollection <IIdentityEquatable> database, ExpectedSideEffects sideEffects)
        {
            if (sideEffects.Inserts != null)
            {
                foreach (var insert in sideEffects.Inserts)
                {
                    // We call insert.IdentityEquals because it doesn't enforce type checking (it may be an IWildcardEntity).
                    Assert.IsTrue(database.Any(_ => insert.IdentityEquals(_)), "Insert was not applied");
                    Assert.IsTrue(database.Any(_ => AreEntitiesEqual(insert, _)), "Insert was applied, but not with expected fields");
                    Assert.IsTrue(snapshot.All(_ => !insert.IdentityEquals(_)), "Cannot assert insert on entity that already exists in snapshot");
                }
            }

            if (sideEffects.Updates != null)
            {
                foreach (var update in sideEffects.Updates)
                {
                    Assert.IsTrue(database.Any(_ => AreEntitiesEqual(update, _)), "Update was not applied");
                    Assert.IsTrue(snapshot.All(_ => !AreEntitiesEqual(update, _)), "Cannot assert update on entity that has not changed since the snapshot");
                    Assert.IsTrue(snapshot.Any(_ => update.IdentityEquals(_)), "Cannot assert update on entity that does not exist in snapshot");
                }
            }

            if (sideEffects.Deletes != null)
            {
                foreach (var delete in sideEffects.Deletes)
                {
                    Assert.IsTrue(database.All(_ => !_.IdentityEquals(delete)), "Delete was not applied");
                }
            }
        }
        private void AssertNoUnexpectedSideEffects(IReadOnlyCollection <IIdentityEquatable> snapshot, IReadOnlyCollection <IIdentityEquatable> database, ExpectedSideEffects sideEffects)
        {
            foreach (var databaseEntity in database)
            {
                if (sideEffects.ExcludedFromTest != null && sideEffects.ExcludedFromTest(databaseEntity))
                {
                    continue;
                }

                var snapshotEntity = snapshot.FirstOrDefault(_ => _.IdentityEquals(databaseEntity));
                if (snapshotEntity == null)
                {
                    if (sideEffects.Inserts == null)
                    {
                        Assert.Fail("Insert was unexpected: " + databaseEntity);
                    }
                    else
                    {
                        Assert.IsTrue(sideEffects.Inserts.Any(_ => AreEntitiesEqual(_, databaseEntity)), "Insert was unexpected: " + databaseEntity);
                    }
                }
                else if (!snapshotEntity.Equals(databaseEntity))
                {
                    if (sideEffects.Updates == null)
                    {
                        Assert.Fail("Update was unexpected: " + databaseEntity);
                    }
                    else
                    {
                        Assert.IsTrue(sideEffects.Updates.Any(_ => AreEntitiesEqual(_, databaseEntity)), "Update was unexpected: " + databaseEntity);
                    }
                }
            }

            foreach (var snapshotEntity in snapshot)
            {
                if (sideEffects.ExcludedFromTest != null && sideEffects.ExcludedFromTest(snapshotEntity))
                {
                    continue;
                }

                if (database.All(_ => !_.IdentityEquals(snapshotEntity)))
                {
                    if (sideEffects.Deletes == null)
                    {
                        Assert.Fail("Delete was unexpected: " + snapshotEntity);
                    }
                    else
                    {
                        Assert.IsTrue(sideEffects.Deletes.Any(_ => AreEntitiesEqual(_, snapshotEntity)), "Delete was unexpected: " + snapshotEntity);
                    }
                }
            }
        }