public async Task Given_SingleEntity_Should_TimeTravel()
        {
            var context = TestHelper.GetNewDbContext();
            var appleId = Guid.Parse("00000002-8803-4263-ada6-cd12a33d8872");

            context.Apples.Add(new Apple {
                Id = appleId, FruitStatus = FruitStatus.Ripe
            });
            await context.SaveChangesAsync();

            var ripeAppleTime = TestHelper.UtcNow;

            context = TestHelper.GetNewDbContext();
            var ripeApple = await context.Apples.SingleAsync(a => a.Id == appleId);

            ripeApple.FruitStatus = FruitStatus.Rotten;
            await context.SaveChangesAsync();

            context = TestHelper.GetNewDbContext();
            var currentApple = await context.Apples.AsNoTracking().SingleAsync(a => a.Id == appleId);

            currentApple.FruitStatus.Should().Be(FruitStatus.Rotten);

            using (TemporalQuery.AsOf(ripeAppleTime))
            {
                var timeTravelApple = await context.Apples.AsNoTracking().SingleAsync(a => a.Id == appleId);

                timeTravelApple.FruitStatus.Should().Be(FruitStatus.Ripe);
            }
        }
Пример #2
0
        private static async Task AssertWormlessFruitStatusAtTime(
            FruitStatus expectedFruitStatus,
            DateTime appleTime,
            Guid appleId)
        {
            using (TemporalQuery.AsOf(appleTime))
            {
                var apple = await GetApple(appleId);

                apple
                .Should()
                .BeEquivalentTo(new { FruitStatus = expectedFruitStatus, Worms = Array.Empty <Worm>() },
                                options => options.ExcludingMissingMembers());
            }
        }
        public async Task Given_IncludedCollection_Should_TimeTravelIncludedCollection()
        {
            var context = TestHelper.GetNewDbContext();
            var appleId = Guid.Parse("00000003-8803-4263-ada6-cd12a33d8872");

            var apple = new Apple {
                Id = appleId, FruitStatus = FruitStatus.Rotten
            };

            apple.AddWorm("Gav");
            context.Apples.Add(apple);

            await context.SaveChangesAsync();

            var rottenAppleTime = TestHelper.UtcNow;

            context = TestHelper.GetNewDbContext();

            apple = await context.Apples.SingleAsync(a => a.Id == appleId);

            apple.AddWorm("G-Dog");
            apple.AddWorm("Gavin' A Laugh");

            await context.SaveChangesAsync();

            context = TestHelper.GetNewDbContext();

            var currentApple = await context.Apples
                               .Include(a => a.Worms)
                               .SingleAsync(a => a.Id == appleId);

            currentApple.Worms.Count.Should().Be(3);

            using (TemporalQuery.AsOf(rottenAppleTime))
            {
                // Let's use the same context for time travel
                var timeTravelApple = await context.Apples
                                      .Include(a => a.Worms)
                                      // All temporal queries must be .AsNoTracking()
                                      .AsNoTracking()
                                      .SingleAsync(a => a.Id == appleId);

                timeTravelApple.Worms.Count.Should().Be(1);
            }
        }
Пример #4
0
        private static async Task AssertWormsNavigationPropertyAtRottenAppleTime(DateTime rottenAppleTime, Guid appleId)
        {
            using (TemporalQuery.AsOf(rottenAppleTime))
            {
                using var localScope = ServiceProvider.CreateScope();
                var context = localScope.ServiceProvider.GetService <ApplicationDbContext>();

                var rottenAppleWorms = await context.Apples
                                       .Where(a => a.Id == appleId)
                                       .SelectMany(a => a.Worms)
                                       .Include(worm => worm.Weapons)
                                       .AsNoTracking().ToListAsync();

                rottenAppleWorms
                .Should()
                .BeEquivalentTo(new[] { new { Name = "Moe", Weapons = new[] { new { Name = "Bazooka" } } } },
                                options => options.ExcludingMissingMembers());
            }
        }
Пример #5
0
        public async Task TemporalQuery_Should_AllowAllTemporalEntitiesToTimeTravel()
        {
            var(appleId, unripeAppleTime, ripeAppleTime, rottenAppleTime) = await SimulateLifecycleOfMyApple();

            // Validate current state of my apple
            var currentApple = await GetApple(appleId);

            currentApple
            .Should()
            .BeEquivalentTo(
                new
            {
                FruitStatus = FruitStatus.Fuzzy,
                Worms       = new object[]
                {
                    new
                    {
                        Name    = "Hairy",
                        Weapons = new[]
                        {
                            new { Name = "Holy Hand Grenade" }, new { Name = "Super Banana Bomb" }
                        },
                        FriendsNames = new[] { "Joan", "Starr", "Curly" }
                    },
                    new { Name = "Curly" },
                    new
                    {
                        Name         = "Moe",
                        Weapons      = new[] { new { Name = "Bazooka Pie" } },
                        FriendsNames = new[] { "John" }
                    }
                }
            }, options => options.ExcludingMissingMembers());

            // Query the state of my apple a prior "system time" when the apple was rotten
            using (TemporalQuery.AsOf(rottenAppleTime))
            {
                var rottenApple = await GetApple(appleId);

                rottenApple
                .Should()
                .BeEquivalentTo(
                    new
                {
                    FruitStatus = FruitStatus.Rotten,
                    Worms       = new object[]
                    {
                        new
                        {
                            Name         = "Moe",
                            Weapons      = new[] { new { Name = "Bazooka" } },
                            FriendsNames = new[] { "John", "Ringo" }
                        }
                    }
                },
                    options => options.ExcludingMissingMembers());
            }


            await Task.WhenAll(new[]
            {
                AssertWormlessFruitStatusAtTime(FruitStatus.Ripe, ripeAppleTime, appleId),
                AssertWormlessFruitStatusAtTime(FruitStatus.Unripe, unripeAppleTime, appleId),
                AssertWormsNavigationPropertyAtRottenAppleTime(rottenAppleTime, appleId)
            });
        }