Esempio n. 1
0
        public async Task RepositoriesCreatedOutsideAsyncContext_TransactionsAreTolerantToConcurrency()
        {
            var repoA = _mongoClient.GetRepository <MyStandaloneEntity>("a");
            var repoB = _mongoClient.GetRepository <MyStandaloneEntity>("b");
            var repoC = _mongoClient.GetRepository <MyStandaloneEntity>("c");

            await repoA.InsertAsync(new MyStandaloneEntity("Jane", new SharedClass("Doe")));

            await repoB.InsertAsync(new MyStandaloneEntity("John", new SharedClass("Doe")));

            await repoC.InsertAsync(new MyStandaloneEntity("Janet", new SharedClass("Doe")));

            var tasks = new Func <Task>[]
            {
                async() =>
                {
                    using (var transaction = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
                    {
                        await repoA.DeleteManyAsync(x => true);

                        transaction.Complete();
                    }
                },
                async() =>
                {
                    using (var transaction = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
                    {
                        await repoB.DeleteManyAsync(x => true);
                    }
                },
                async() =>
                {
                    await repoC.WithTransactionAsync(async() =>
                    {
                        await repoC.DeleteManyAsync(x => true);
                    }, TransactionType.TransactionScope);
                },
                async() =>
                {
                    using (var transaction = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
                    {
                        var repoD = _mongoClient.GetRepository <MyStandaloneEntity>("d");

                        await Task.Delay(1);

                        await MyStaticInserter.InsertDocument(new MyStandaloneEntity("Jeff", new SharedClass("Doe")), repoD);

                        MyStaticInserter.InsertDocument(new MyStandaloneEntity("Jeff", new SharedClass("Doe")), repoD).Wait();

                        // No commit
                    }
                },
            }
            .AsParallel()
            .WithDegreeOfParallelism(4)
            .WithExecutionMode(ParallelExecutionMode.ForceParallelism)
            .Select(async x => await x());

            await Task.WhenAll(tasks);

            var jane = await repoA.GetAll().SingleOrDefaultAsync();

            var john = await repoB.GetAll().SingleOrDefaultAsync();

            var janet = await repoC.GetAll().SingleOrDefaultAsync();

            var jeff = await _mongoClient.GetRepository <MyStandaloneEntity>("d").GetAll().SingleOrDefaultAsync();

            jane.Should().BeNull();
            john.Name.Should().Be("John");
            janet.Should().BeNull();
            jeff.Should().BeNull();
        }
        public async Task ShouldUseTheRightSessionInAMultiThreadedScenarioWithExplicitTransaction()
        {
            var request1 = Task.Run(async() =>
            {
                var repo = _mongoClient.GetRepository <DummyEntity>("tenant_a");

                using (var transaction = repo.StartTransaction())
                {
                    await repo.InsertAsync(new DummyEntity("Hello!"));

                    await transaction.CommitAsync();
                }
            });

            var request2 = Task.Run(async() =>
            {
                var repo = _mongoClient.GetRepository <DummyEntity>("tenant_b");

                using (var transaction = repo.StartTransaction())
                {
                    await Task.Run(async() => await repo.InsertAsync(new DummyEntity("Hola!")));

                    // No commit
                }
            });

            var request3 = Task.Run(async() =>
            {
                var repo = _mongoClient.GetRepository <DummyEntity>("tenant_a");

                using (var transaction = repo.StartTransaction())
                {
                    await Task.Run(async() => await repo.InsertAsync(new DummyEntity("Hello again!")));

                    // No commit
                }
            });

            var request4 = Task.Run(async() =>
            {
                var repo = _mongoClient.GetRepository <DummyEntity>("tenant_a");
                using (var transaction = repo.StartTransaction())
                {
                    await Task.Delay(50);
                    await repo.InsertAsync(new DummyEntity("Hello good sir or madam!"));

                    await transaction.CommitAsync();
                }
            });

            var request5 = Task.Run(async() =>
            {
                var repo = _mongoClient.GetRepository <DummyEntity>("tenant_b");

                using (var transaction = repo.StartTransaction())
                {
                    await MyStaticInserter.InsertDocument(new DummyEntity("Hola senor"), repo);
                    MyStaticInserter.InsertDocument(new DummyEntity("Hola senor"), repo).Wait();

                    await transaction.CommitAsync();
                }
            });

            await Task.WhenAll(request1, request2, request3, request4, request5);

            var allDocumentsForTenantA = await _mongoClient.GetRepository <DummyEntity>("tenant_a").GetAll().ToListAsync();

            var allDocumentsForTenantB = await _mongoClient.GetRepository <DummyEntity>("tenant_b").GetAll().ToListAsync();

            allDocumentsForTenantA.Should().HaveCount(2);
            allDocumentsForTenantB.Should().HaveCount(2);

            allDocumentsForTenantA.Should().ContainSingle(x => x.MyProperty == "Hello!");
            allDocumentsForTenantA.Should().ContainSingle(x => x.MyProperty == "Hello good sir or madam!");
            allDocumentsForTenantB.Count(x => x.MyProperty == "Hola senor").Should().Be(2);
        }