/// <summary>
 ///     Constructs the DbContextTransaction object with the associated connection object
 ///     and with the given isolation level
 /// </summary>
 /// <param name="connection">The EntityConnection object owning this transaction </param>
 /// <param name="isolationLevel">The database isolation level with which the underlying store transaction will be created</param>
 internal DbContextTransaction(EntityConnection connection, IsolationLevel isolationLevel)
 {
     DebugCheck.NotNull(connection);
     _connection = connection;
     EnsureOpenConnection();
     _entityTransaction = _connection.BeginTransaction(isolationLevel);
 }
Example #2
0
            public void ExecutionStrategy_is_used_to_recover_from_a_transient_error()
            {
                var storeConnectionState = ConnectionState.Open;
                var transientExceptionThrown = false;
                var storeConnectionMock = new Mock<DbConnection>(MockBehavior.Strict);
                storeConnectionMock.Setup(m => m.Close()).Callback(() => storeConnectionState = ConnectionState.Closed);
                storeConnectionMock.Setup(m => m.Open()).Callback(() => storeConnectionState = ConnectionState.Open);
                storeConnectionMock.SetupGet(m => m.DataSource).Returns("fake");
                storeConnectionMock.SetupGet(m => m.State).Returns(() => storeConnectionState);
                storeConnectionMock.Protected().Setup<DbTransaction>("BeginDbTransaction", IsolationLevel.Unspecified)
                                   .Returns<IsolationLevel>(
                                       il =>
                                           {
                                               if (!transientExceptionThrown)
                                               {
                                                   transientExceptionThrown = true;
                                                   storeConnectionState = ConnectionState.Broken;
                                                   throw new TimeoutException();
                                               }
                                               return new Mock<DbTransaction>().Object;
                                           });

                var entityConnection = new EntityConnection(CreateMetadataWorkspaceMock().Object, storeConnectionMock.Object, true, true);

                var executionStrategyMock = new Mock<IDbExecutionStrategy>();
                executionStrategyMock.Setup(m => m.Execute(It.IsAny<Func<DbTransaction>>())).Returns<Func<DbTransaction>>(
                    a =>
                        {
                            storeConnectionMock.Protected()
                                               .Verify<DbTransaction>(
                                                   "BeginDbTransaction", Times.Never(), IsolationLevel.Unspecified);

                            Assert.Throws<TimeoutException>(() => a());

                            storeConnectionMock.Protected()
                                               .Verify<DbTransaction>(
                                                   "BeginDbTransaction", Times.Once(), IsolationLevel.Unspecified);

                            var result = a();

                            storeConnectionMock.Protected()
                                               .Verify<DbTransaction>(
                                                   "BeginDbTransaction", Times.Exactly(2), IsolationLevel.Unspecified);

                            return result;
                        });

                MutableResolver.AddResolver<Func<IDbExecutionStrategy>>(key => (Func<IDbExecutionStrategy>)(() => executionStrategyMock.Object));
                try
                {
                    entityConnection.BeginTransaction();
                }
                finally
                {
                    MutableResolver.ClearResolvers();
                }

                executionStrategyMock.Verify(m => m.Execute(It.IsAny<Func<DbTransaction>>()), Times.Once());
            }
            public void Should_use_interception()
            {
                var mockConnection = new Mock<DbConnection>();
                mockConnection.SetupGet(m => m.DataSource).Returns("Foo");
                mockConnection.SetupGet(m => m.State).Returns(ConnectionState.Open);

                var mockStoreItemCollection = new Mock<StoreItemCollection>();
                mockStoreItemCollection
                    .SetupGet(m => m.ProviderFactory)
                    .Returns(DbProviderServices.GetProviderFactory(new SqlConnection()));

                var mockMetadataWorkspace = new Mock<MetadataWorkspace>();
                mockMetadataWorkspace
                    .Setup(m => m.GetItemCollection(DataSpace.SSpace))
                    .Returns(mockStoreItemCollection.Object);

                var objectContext = new ObjectContext();

                var mockTransaction = new Mock<DbTransaction>();

                var mockConnectionInterceptor = new Mock<IDbConnectionInterceptor>();
                mockConnectionInterceptor
                    .Setup(m => m.BeginningTransaction(mockConnection.Object, It.IsAny<BeginTransactionInterceptionContext>()))
                    .Callback<DbConnection, BeginTransactionInterceptionContext>(
                        (_, c) =>
                        {
                            Assert.Equal(new[] { objectContext }, c.ObjectContexts);
                            Assert.Equal(IsolationLevel.Chaos, c.IsolationLevel);
                        });

                mockConnectionInterceptor
                    .Setup(m => m.BeganTransaction(mockConnection.Object, It.IsAny<BeginTransactionInterceptionContext>()))
                    .Callback<DbConnection, BeginTransactionInterceptionContext>(
                        (_, c) =>
                        {
                            Assert.Equal(new[] { objectContext }, c.ObjectContexts);
                            Assert.Equal(IsolationLevel.Chaos, c.IsolationLevel);
                            Assert.Same(mockTransaction.Object, c.Result);
                        });

                mockConnection
                    .Protected()
                    .Setup<DbTransaction>("BeginDbTransaction", ItExpr.IsAny<IsolationLevel>())
                    .Returns(mockTransaction.Object);

                EntityConnection connection;
                DbInterception.Add(mockConnectionInterceptor.Object);
                try
                {
                    connection
                        = new EntityConnection(
                            mockMetadataWorkspace.Object,
                            mockConnection.Object,
                            true,
                            true);
                    connection.AssociateContext(objectContext);
                    connection.BeginTransaction(IsolationLevel.Chaos);
                }
                finally
                {
                    DbInterception.Remove(mockConnectionInterceptor.Object);
                }

                mockConnectionInterceptor.Verify(
                    m => m.BeginningTransaction(mockConnection.Object, It.IsAny<BeginTransactionInterceptionContext>()), Times.Once());
                mockConnectionInterceptor.Verify(
                    m => m.BeganTransaction(mockConnection.Object, It.IsAny<BeginTransactionInterceptionContext>()), Times.Once());
                mockConnection
                    .Protected()
                    .Verify<DbTransaction>("BeginDbTransaction", Times.Once(), ItExpr.IsAny<IsolationLevel>());

                mockConnectionInterceptor.Verify(
                    m => m.StateGetting(It.IsAny<DbConnection>(), It.IsAny<DbConnectionInterceptionContext<ConnectionState>>()),
                    Times.Exactly(3));
                mockConnectionInterceptor.Verify(
                    m => m.StateGot(It.IsAny<DbConnection>(), It.IsAny<DbConnectionInterceptionContext<ConnectionState>>()),
                    Times.Exactly(3));
                mockConnection.Verify(m => m.State, Times.Exactly(3));

                Assert.Equal(ConnectionState.Open, connection.State);
            }