示例#1
0
            public void DbDeleteDatabase_dispatches_commands_to_interceptors_for_connections_with_initial_catalog()
            {
                using (var context = new DdlDatabaseContext())
                {
                    context.Database.CreateIfNotExists();
                }

                var interceptor = new TestNonQueryInterceptor();

                Interception.AddInterceptor(interceptor);
                try
                {
                    using (var connection = new SqlConnection(SimpleAttachConnectionString <DdlDatabaseContext>()))
                    {
                        SqlProviderServices.Instance.DeleteDatabase(connection, null, new StoreItemCollection());
                    }
                }
                finally
                {
                    Interception.RemoveInterceptor(interceptor);
                }

                Assert.Equal(1, interceptor.Commands.Count);

                Assert.Equal(
                    "drop database [System.Data.Entity.SqlServer.SqlProviderServicesTests+DdlDatabaseContext]",
                    interceptor.Commands.Select(c => c.CommandText).Single());
            }
示例#2
0
            public void DbCreateDatabase_dispatches_commands_to_interceptors()
            {
                using (var context = new DdlDatabaseContext(SimpleCeConnection <DdlDatabaseContext>()))
                {
                    var storeItemCollection =
                        (StoreItemCollection)
                        ((IObjectContextAdapter)context).ObjectContext.MetadataWorkspace.GetItemCollection(DataSpace.SSpace);

                    context.Database.Delete();

                    var interceptor = new TestNonQueryInterceptor();
                    Interception.AddInterceptor(interceptor);
                    try
                    {
                        SqlCeProviderServices.Instance.CreateDatabase(context.Database.Connection, null, storeItemCollection);
                    }
                    finally
                    {
                        Interception.RemoveInterceptor(interceptor);
                    }

                    Assert.Equal(3, interceptor.CommandTexts.Count);

                    Assert.True(interceptor.CommandTexts.Any(t => t.StartsWith("CREATE TABLE \"Products\" ")));
                    Assert.True(interceptor.CommandTexts.Any(t => t.StartsWith("CREATE TABLE \"Categories\" ")));
                    Assert.True(interceptor.CommandTexts.Any(t => t.StartsWith("ALTER TABLE \"Products\" ADD CONSTRAINT ")));
                }
            }
示例#3
0
            public void DbDatabaseExists_dispatches_commands_to_interceptors_for_connections_with_no_initial_catalog()
            {
                var interceptor = new TestScalarInterceptor();

                Interception.AddInterceptor(interceptor);
                try
                {
                    using (var connection =
                               new SqlConnection(ModelHelpers.SimpleAttachConnectionString("I.Do.Not.Exist", useInitialCatalog: false)))
                    {
                        SqlProviderServices.Instance.DatabaseExists(connection, null, new StoreItemCollection());
                    }
                }
                finally
                {
                    Interception.RemoveInterceptor(interceptor);
                }

                Assert.Equal(1, interceptor.Commands.Count);

                Assert.True(
                    interceptor.Commands.Select(c => c.CommandText)
                    .Single()
                    .StartsWith("SELECT Count(*) FROM sys.master_files WHERE [physical_name]=N'"));
            }
示例#4
0
            public void DbCreateDatabase_dispatches_commands_to_interceptors()
            {
                using (var context = new DdlDatabaseContext())
                {
                    var storeItemCollection =
                        (StoreItemCollection)
                        ((IObjectContextAdapter)context).ObjectContext.MetadataWorkspace.GetItemCollection(DataSpace.SSpace);

                    context.Database.Delete();

                    var interceptor = new TestNonQueryInterceptor();
                    Interception.AddInterceptor(interceptor);
                    try
                    {
                        SqlProviderServices.Instance.CreateDatabase(context.Database.Connection, null, storeItemCollection);
                    }
                    finally
                    {
                        Interception.RemoveInterceptor(interceptor);
                    }

                    Assert.Equal(3, interceptor.Commands.Count);

                    var commandTexts = interceptor.Commands.Select(c => c.CommandText);
                    Assert.True(commandTexts.Any(t => t.StartsWith("create database ")));
                    Assert.True(commandTexts.Any(t => t.StartsWith("if serverproperty('EngineEdition') <> 5 execute sp_executesql ")));
                    Assert.True(commandTexts.Any(t => t.StartsWith("create table [dbo].[Categories] ")));
                }
            }
示例#5
0
        public void AnyModelTableExists_dispatches_to_interceptors()
        {
            var connectionMock = new Mock <DbConnection>
            {
                CallBase = true
            };
            var internalContextMock = new Mock <InternalContext>();
            var dbCommandMock       = new Mock <DbCommand>();

            SetupMocksForTableChecking(dbCommandMock, connectionMock, internalContextMock);

            var interceptorMock = new Mock <DbInterceptor>
            {
                CallBase = true
            };

            Interception.AddInterceptor(interceptorMock.Object);
            try
            {
                new DatabaseTableChecker().AnyModelTableExists(new FakeContext(connectionMock.Object, internalContextMock.Object));
            }
            finally
            {
                Interception.RemoveInterceptor(interceptorMock.Object);
            }

            interceptorMock.Verify(
                m => m.ReaderExecuting(
                    dbCommandMock.Object, CommandBehavior.Default,
                    It.Is <DbInterceptionContext>(c => c.ObjectContexts.Contains(internalContextMock.Object.ObjectContext))));
        }
        public void ExecuteSql_with_transactions_suppressed_dispatches_commands_to_interceptors()
        {
            var mockCommand = new Mock <DbCommand>();

            mockCommand.Setup(m => m.ExecuteNonQuery()).Returns(2013);

            var mockConnection = new Mock <DbConnection>();

            mockConnection.Protected().Setup <DbCommand>("CreateDbCommand").Returns(mockCommand.Object);

            var mockTransaction = new Mock <DbTransaction>();

            mockTransaction.Protected().Setup <DbConnection>("DbConnection").Returns(mockConnection.Object);

            var mockFactory = new Mock <DbProviderFactory>();

            mockFactory.Setup(m => m.CreateConnection()).Returns(mockConnection.Object);

            var objectContext       = new ObjectContext();
            var mockInternalContext = new Mock <InternalContextForMock>();

            mockInternalContext.Setup(m => m.ObjectContext).Returns(objectContext);
            var context = mockInternalContext.Object.Owner;

            objectContext.InterceptionContext = objectContext.InterceptionContext.WithDbContext(context);

            var migrator  = new DbMigrator(context, mockFactory.Object);
            var statement = new MigrationStatement
            {
                Sql = "Some Sql",
                SuppressTransaction = true
            };

            var mockInterceptor = new Mock <DbInterceptor> {
                CallBase = true
            };

            Interception.AddInterceptor(mockInterceptor.Object);

            try
            {
                migrator.ExecuteSql(mockTransaction.Object, statement);
            }
            finally
            {
                Interception.RemoveInterceptor(mockInterceptor.Object);
            }

            mockInterceptor.Verify(m => m.NonQueryExecuting(
                                       mockCommand.Object,
                                       It.Is <DbInterceptionContext>(c => c.DbContexts.Contains(context))));

            mockInterceptor.Verify(m => m.NonQueryExecuted(
                                       mockCommand.Object,
                                       2013,
                                       It.Is <DbInterceptionContext>(c => c.DbContexts.Contains(context))));
        }
        public void Async_commands_that_are_canceled_are_still_intercepted()
        {
            var logger = new CommandLogger();

            Interception.AddInterceptor(logger);

            var cancellation      = new CancellationTokenSource();
            var cancellationToken = cancellation.Token;

            try
            {
                using (var context = new BlogContextNoInit())
                {
                    context.Database.Connection.Open();

                    cancellation.Cancel();

                    var command = context.Database.ExecuteSqlCommandAsync("update Blogs set Title = 'No' where Id = -1", cancellationToken);

                    try
                    {
                        command.Wait();
                    }
                    catch (AggregateException)
                    {
                        // Ignore
                    }

                    Assert.True(command.IsCanceled);

                    context.Database.Connection.Close();
                }
            }
            finally
            {
                Interception.RemoveInterceptor(logger);
            }

            Assert.Equal(2, logger.Log.Count);

            var executingLog = logger.Log[0];

            Assert.Equal(CommandMethod.NonQueryExecuting, executingLog.Method);
            Assert.True(executingLog.IsAsync);
            Assert.Null(executingLog.Result);
            Assert.Null(executingLog.Exception);

            var executedLog = logger.Log[1];

            Assert.Equal(CommandMethod.NonQueryExecuted, executedLog.Method);
            Assert.True(executedLog.IsAsync);
            Assert.Equal(0, executedLog.Result);
            Assert.Null(executedLog.Exception);
            Assert.True(executedLog.TaskStatus.HasFlag(TaskStatus.Canceled));
        }
        public void Initialization_and_simple_query_and_update_commands_can_be_logged()
        {
            var logger = new CommandLogger();

            Interception.AddInterceptor(logger);

            try
            {
                using (var context = new BlogContextLogAll())
                {
                    BlogContext.DoStuff(context);
                }
            }
            finally
            {
                Interception.RemoveInterceptor(logger);
            }

            var commandsUsed = new bool[Enum.GetValues(typeof(CommandMethod)).Length];

            for (var i = 0; i < logger.Log.Count; i++)
            {
                var method = logger.Log[i].Method;
                commandsUsed[(int)method] = true;

                if (method.ToString().EndsWith("Executing"))
                {
                    Assert.Equal(method + 1, logger.Log[i + 1].Method);
                    Assert.Same(logger.Log[i].Command, logger.Log[i + 1].Command);
                }
            }

            // Check that every type of command used has log entries
            Assert.True(commandsUsed[(int)CommandMethod.NonQueryExecuting]);
            Assert.True(commandsUsed[(int)CommandMethod.NonQueryExecuted]);
            Assert.True(commandsUsed[(int)CommandMethod.ReaderExecuting]);
            Assert.True(commandsUsed[(int)CommandMethod.ReaderExecuted]);
            Assert.True(commandsUsed[(int)CommandMethod.ScalarExecuting]);
            Assert.True(commandsUsed[(int)CommandMethod.ScalarExecuted]);

            // Sanity check on command text
            var commandTexts = logger.Log.Select(l => l.CommandText.ToLowerInvariant());

            Assert.True(commandTexts.Any(c => c.StartsWith("select")));
            Assert.True(commandTexts.Any(c => c.StartsWith("create")));
            Assert.True(commandTexts.Any(c => c.StartsWith("alter")));
            Assert.True(commandTexts.Any(c => c.StartsWith("insert")));
        }
        public void Command_trees_for_initialization_and_simple_query_and_update_commands_can_be_logged()
        {
            // Make sure that HistoryContext has been used to ensure test runs consistently regardless of
            // whether or not other tests have run before it.
            using (var initContext = new BlogContextNoInit())
            {
                initContext.Database.Initialize(force: false);
            }

            var logger = new CommandTreeLogger();

            Interception.AddInterceptor(logger);

            BlogContextLogAll context;

            try
            {
                using (context = new BlogContextLogAll())
                {
                    BlogContext.DoStuff(context);
                }
            }
            finally
            {
                Interception.RemoveInterceptor(logger);
            }

            // Sanity check that we got tree creations logged
            Assert.True(logger.Log.OfType <DbQueryCommandTree>().Any(t => t.DataSpace == DataSpace.CSpace));
            Assert.True(logger.Log.OfType <DbQueryCommandTree>().Any(t => t.DataSpace == DataSpace.SSpace));
            Assert.True(logger.Log.OfType <DbInsertCommandTree>().Any(t => t.DataSpace == DataSpace.SSpace));
#if !NET40
            Assert.True(logger.Log.OfType <DbUpdateCommandTree>().Any(t => t.DataSpace == DataSpace.SSpace));

            Assert.True(
                logger.Log.OfType <DbUpdateCommandTree>()
                .Any(
                    t => t.SetClauses.OfType <DbSetClause>()
                    .Any(
                        c => ((DbPropertyExpression)c.Property).Property.Name == "Title" &&
                        (string)((DbConstantExpression)c.Value).Value == "I'm a logger and I'm okay...")));
#endif

            foreach (var interceptionContext in logger.LogWithContext.Select(t => t.Item2))
            {
                Assert.Contains(context, interceptionContext.DbContexts);
            }
        }
            public void Executes_reader_from_store_provider_command_and_returns_it()
            {
                var entityCommand = InitializeEntityCommand();

                var dbDataReader  = new Mock <DbDataReader>().Object;
                var dbCommandMock = new Mock <DbCommand>();

                dbCommandMock.Protected().Setup <DbDataReader>("ExecuteDbDataReader", It.IsAny <CommandBehavior>()).Returns(dbDataReader);
                var dbCommandDefinitionMock = new Mock <DbCommandDefinition>();

                dbCommandDefinitionMock.Setup(m => m.CreateCommand()).Returns(dbCommandMock.Object);
                var mappedCommandDefinitions = new List <DbCommandDefinition>
                {
                    dbCommandDefinitionMock.Object
                };

                var entityCommandDefinitionMock = new Mock <EntityCommandDefinition>(null, null, mappedCommandDefinitions)
                {
                    CallBase = true
                };

                var mockInterceptor = new Mock <DbInterceptor>
                {
                    CallBase = true
                };

                Interception.AddInterceptor(mockInterceptor.Object);

                try
                {
                    Assert.Same(
                        dbDataReader, entityCommandDefinitionMock.Object.ExecuteStoreCommands(entityCommand, CommandBehavior.Default));
                }
                finally
                {
                    Interception.RemoveInterceptor(mockInterceptor.Object);
                }

                dbCommandMock.Protected().Verify("ExecuteDbDataReader", Times.Once(), CommandBehavior.Default);
                mockInterceptor.Verify(
                    m => m.ReaderExecuting(dbCommandMock.Object, CommandBehavior.Default, entityCommand.InterceptionContext));
                mockInterceptor.Verify(
                    m =>
                    m.ReaderExecuted(
                        dbCommandMock.Object, CommandBehavior.Default, It.IsAny <DbDataReader>(), entityCommand.InterceptionContext));
            }
示例#11
0
            public void DbDeleteDatabase_dispatches_commands_to_interceptors_for_connections_without_initial_catalog()
            {
                StoreItemCollection storeItemCollection;

                using (var context = new DdlDatabaseContext())
                {
                    storeItemCollection =
                        (StoreItemCollection)
                        ((IObjectContextAdapter)context).ObjectContext.MetadataWorkspace.GetItemCollection(DataSpace.SSpace);
                }

                using (var connection = new SqlConnection(SimpleAttachConnectionString <DdlDatabaseContext>(useInitialCatalog: false)))
                {
                    if (!SqlProviderServices.Instance.DatabaseExists(connection, null, storeItemCollection))
                    {
                        SqlProviderServices.Instance.CreateDatabase(connection, null, storeItemCollection);
                    }

                    var nonQueryInterceptor = new TestNonQueryInterceptor();
                    var readerInterceptor   = new TestReaderInterceptor();
                    Interception.AddInterceptor(nonQueryInterceptor);
                    Interception.AddInterceptor(readerInterceptor);
                    try
                    {
                        SqlProviderServices.Instance.DeleteDatabase(connection, null, storeItemCollection);
                    }
                    finally
                    {
                        Interception.RemoveInterceptor(nonQueryInterceptor);
                        Interception.RemoveInterceptor(readerInterceptor);
                    }

                    Assert.Equal(2, nonQueryInterceptor.Commands.Count);

                    var commandTexts = nonQueryInterceptor.Commands.Select(c => c.CommandText);
                    Assert.True(commandTexts.Any(t => t.StartsWith("drop database [SYSTEM_DATA_ENTITY_SQLSERVER")));
                    Assert.True(
                        commandTexts.Any(t => t.Contains("SYSTEM.DATA.ENTITY.SQLSERVER.SQLPROVIDERSERVICESTESTS+DDLDATABASECONTEXT.MDF")));

                    Assert.Equal(1, readerInterceptor.Commands.Count);

                    Assert.True(
                        readerInterceptor.Commands.Select(
                            c => c.CommandText).Single().StartsWith("SELECT [d].[name] FROM sys.databases "));
                }
            }
            public void GetServerType_dispatches_commands_to_interceptors()
            {
                var connection = CreateConnectionForAzureQuery(5).Object;

                var interceptor = new TestReaderInterceptor();

                Interception.AddInterceptor(interceptor);
                try
                {
                    SqlVersionUtils.GetServerType(connection);
                }
                finally
                {
                    Interception.RemoveInterceptor(interceptor);
                }

                Assert.Equal(1, interceptor.Commands.Count);
                Assert.Same(connection.CreateCommand(), interceptor.Commands.Single());
            }
        public void Async_commands_that_result_in_exceptions_are_still_intercepted()
        {
            var logger = new CommandLogger();

            Interception.AddInterceptor(logger);

            try
            {
                using (var context = new BlogContextNoInit())
                {
                    var query = context.Blogs.SqlQuery("select * from No.Chance").ToListAsync();

                    Assert.Throws <AggregateException>(() => query.Wait());

                    Assert.True(query.IsFaulted);
                }
            }
            finally
            {
                Interception.RemoveInterceptor(logger);
            }

            Assert.Equal(2, logger.Log.Count);

            var executingLog = logger.Log[0];

            Assert.Equal(CommandMethod.ReaderExecuting, executingLog.Method);
            Assert.True(executingLog.IsAsync);
            Assert.Null(executingLog.Result);
            Assert.Null(executingLog.Exception);

            var executedLog = logger.Log[1];

            Assert.Equal(CommandMethod.ReaderExecuted, executedLog.Method);
            Assert.True(executedLog.IsAsync);
            Assert.Null(executedLog.Result);
            Assert.IsType <SqlException>(executedLog.Exception);
            Assert.True(executedLog.TaskStatus.HasFlag(TaskStatus.Faulted));
        }
示例#14
0
        public void ExecuteSql_dispatches_commands_to_interceptors()
        {
            var mockCommand = new Mock <DbCommand>();

            mockCommand.Setup(m => m.ExecuteNonQuery()).Returns(2013);

            var mockConnection = new Mock <DbConnection>();

            mockConnection.Protected().Setup <DbCommand>("CreateDbCommand").Returns(mockCommand.Object);

            var mockTransaction = new Mock <DbTransaction>();

            mockTransaction.Protected().Setup <DbConnection>("DbConnection").Returns(mockConnection.Object);

            var migrator  = new DbMigrator();
            var statement = new MigrationStatement
            {
                Sql = "Some Sql"
            };

            var mockInterceptor = new Mock <DbCommandInterceptor> {
                CallBase = true
            };

            Interception.AddInterceptor(mockInterceptor.Object);

            try
            {
                migrator.ExecuteSql(mockTransaction.Object, statement);
            }
            finally
            {
                Interception.RemoveInterceptor(mockInterceptor.Object);
            }

            mockInterceptor.Verify(m => m.NonQueryExecuting(mockCommand.Object, It.IsAny <DbCommandInterceptionContext <int> >()));
            mockInterceptor.Verify(m => m.NonQueryExecuted(mockCommand.Object, It.IsAny <DbCommandInterceptionContext <int> >()));
        }
示例#15
0
        public void AnyModelTableExists_dispatches_to_interceptors()
        {
            var connectionMock = new Mock <DbConnection>
            {
                CallBase = true
            };
            var internalContextMock = new Mock <InternalContext>();
            var dbCommandMock       = new Mock <DbCommand>();

            var mockOperations = new Mock <DatabaseOperations>();

            mockOperations.Setup(m => m.Exists(It.IsAny <ObjectContext>())).Returns(true);
            internalContextMock.Setup(m => m.DatabaseOperations).Returns(mockOperations.Object);

            SetupMocksForTableChecking(dbCommandMock, connectionMock, internalContextMock);

            var interceptorMock = new Mock <DbCommandInterceptor>
            {
                CallBase = true
            };

            Interception.AddInterceptor(interceptorMock.Object);
            try
            {
                new DatabaseTableChecker().AnyModelTableExists(internalContextMock.Object);
            }
            finally
            {
                Interception.RemoveInterceptor(interceptorMock.Object);
            }

            interceptorMock.Verify(
                m => m.ScalarExecuting(
                    dbCommandMock.Object,
                    It.Is <DbCommandInterceptionContext <object> >(c => c.ObjectContexts.Contains(internalContextMock.Object.ObjectContext))));
        }
        public void Commands_that_result_in_exceptions_are_still_intercepted()
        {
            var logger = new CommandLogger();

            Interception.AddInterceptor(logger);

            Exception exception;

            try
            {
                using (var context = new BlogContextNoInit())
                {
                    exception = Assert.Throws <SqlException>(() => context.Blogs.SqlQuery("select * from No.Chance").ToList());
                }
            }
            finally
            {
                Interception.RemoveInterceptor(logger);
            }

            Assert.Equal(2, logger.Log.Count);

            var executingLog = logger.Log[0];

            Assert.Equal(CommandMethod.ReaderExecuting, executingLog.Method);
            Assert.False(executingLog.IsAsync);
            Assert.Null(executingLog.Result);
            Assert.Null(executingLog.Exception);

            var executedLog = logger.Log[1];

            Assert.Equal(CommandMethod.ReaderExecuted, executedLog.Method);
            Assert.False(executedLog.IsAsync);
            Assert.Null(executedLog.Result);
            Assert.Same(exception, executedLog.Exception);
        }
        public void Multiple_contexts_running_concurrently_can_log_command_trees_except_trees_for_cached_queries()
        {
            // Make sure no logs get initialization trees
            using (var context = new BlogContextNoInit())
            {
                context.Database.Initialize(force: false);
            }

            // Run the test code once to log both update and query trees
            using (var context = new BlogContextNoInit())
            {
                var logger = new CommandTreeLogger(context);
                Interception.AddInterceptor(logger);

                try
                {
                    BlogContext.DoStuff(context);
                }
                finally
                {
                    Interception.RemoveInterceptor(logger);
                }

#if NET40
                Assert.Equal(4, logger.Log.Count);
#else
                Assert.Equal(5, logger.Log.Count);
#endif

                Assert.True(logger.Log.OfType <DbQueryCommandTree>().Any(t => t.DataSpace == DataSpace.CSpace));
                Assert.True(logger.Log.OfType <DbInsertCommandTree>().Any(t => t.DataSpace == DataSpace.SSpace));
#if !NET40
                Assert.True(logger.Log.OfType <DbUpdateCommandTree>().Any(t => t.DataSpace == DataSpace.SSpace));
#endif
            }

            // Now run again multiple times concurrently--only update trees logged
            var loggers = new ConcurrentBag <CommandTreeLogger>();

            const int executionCount = 5;
            ExecuteInParallel(
                () =>
            {
                using (var context = new BlogContextNoInit())
                {
                    var logger = new CommandTreeLogger(context);
                    Interception.AddInterceptor(logger);
                    loggers.Add(logger);

                    try
                    {
                        BlogContext.DoStuff(context);
                    }
                    finally
                    {
                        Interception.RemoveInterceptor(logger);
                    }
                }
            }, executionCount);

            Assert.Equal(executionCount, loggers.Count);

            foreach (var logger in loggers)
            {
#if NET40
                Assert.Equal(1, logger.Log.Count);
#else
                Assert.Equal(2, logger.Log.Count);
#endif

                Assert.False(logger.Log.OfType <DbQueryCommandTree>().Any(t => t.DataSpace == DataSpace.CSpace));
                Assert.True(logger.Log.OfType <DbInsertCommandTree>().Any(t => t.DataSpace == DataSpace.SSpace));
#if !NET40
                Assert.True(logger.Log.OfType <DbUpdateCommandTree>().Any(t => t.DataSpace == DataSpace.SSpace));
#endif
            }
        }
        public void Initialization_and_simple_query_and_update_commands_can_be_logged()
        {
            var logger = new CommandLogger();

            Interception.AddInterceptor(logger);

            try
            {
                using (var context = new BlogContextLogAll())
                {
                    BlogContext.DoStuff(context);
                }
            }
            finally
            {
                Interception.RemoveInterceptor(logger);
            }

            var commandsUsed = new bool[Enum.GetValues(typeof(CommandMethod)).Length];

            // Check that every "executed" call is preceded by an "executing" call.
            // (The reverse is not true since "executed" is not called for operations that throw.)
            for (var i = 0; i < logger.Log.Count; i++)
            {
                var method = logger.Log[i].Method;
                commandsUsed[(int)method] = true;

                if (method.ToString().EndsWith("Executed"))
                {
                    Assert.Equal(method - 1, logger.Log[i - 1].Method);
                }
            }

            // Check that every type of command used has log entries
            Assert.True(commandsUsed[(int)CommandMethod.NonQueryExecuting]);
            Assert.True(commandsUsed[(int)CommandMethod.NonQueryExecuted]);
            Assert.True(commandsUsed[(int)CommandMethod.ReaderExecuting]);
            Assert.True(commandsUsed[(int)CommandMethod.ReaderExecuted]);
            Assert.True(commandsUsed[(int)CommandMethod.ScalarExecuting]);
            Assert.True(commandsUsed[(int)CommandMethod.ScalarExecuted]);

#if NET40
            Assert.False(commandsUsed[(int)CommandMethod.AsyncNonQueryExecuting]);
            Assert.False(commandsUsed[(int)CommandMethod.AsyncNonQueryExecuted]);
            Assert.False(commandsUsed[(int)CommandMethod.AsyncReaderExecuting]);
            Assert.False(commandsUsed[(int)CommandMethod.AsyncReaderExecuted]);
#else
            Assert.True(commandsUsed[(int)CommandMethod.AsyncNonQueryExecuting]);
            Assert.True(commandsUsed[(int)CommandMethod.AsyncNonQueryExecuted]);
            Assert.True(commandsUsed[(int)CommandMethod.AsyncReaderExecuting]);
            Assert.True(commandsUsed[(int)CommandMethod.AsyncReaderExecuted]);
#endif

            // EF and SQL provider never send ExecuteScalarAsync
            Assert.False(commandsUsed[(int)CommandMethod.AsyncScalarExecuting]);
            Assert.False(commandsUsed[(int)CommandMethod.AsyncScalarExecuted]);

            // Sanity check on command text
            var commandTexts = logger.Log.Select(l => l.CommandText.ToLowerInvariant());
            Assert.True(commandTexts.Any(c => c.StartsWith("select")));
            Assert.True(commandTexts.Any(c => c.StartsWith("create")));
            Assert.True(commandTexts.Any(c => c.StartsWith("alter")));
            Assert.True(commandTexts.Any(c => c.StartsWith("insert")));
#if !NET40
            Assert.True(commandTexts.Any(c => c.StartsWith("update")));
#endif

            // Sanity check on results
            Assert.True(logger.Log.Where(l => l.Method == CommandMethod.NonQueryExecuted).All(l => l.Result != null));
            Assert.True(logger.Log.Where(l => l.Method == CommandMethod.ReaderExecuted).All(l => l.Result != null));

#if !NET40
            Assert.True(
                logger.Log.Where(
                    l => l.Method.ToString().StartsWith("Async") &&
                    l.Method.ToString().EndsWith("Executed")).All(l => l.Result != null));
#endif
        }
        public void Multiple_contexts_running_concurrently_can_use_interception()
        {
            var loggers = new ConcurrentBag <CommandLogger>();

            const int executionCount = 5;

            ExecuteInParallel(
                () =>
            {
                using (var context = new BlogContextNoInit())
                {
                    var logger = new CommandLogger(context);
                    Interception.AddInterceptor(logger);
                    loggers.Add(logger);

                    try
                    {
                        BlogContext.DoStuff(context);
                    }
                    finally
                    {
                        Interception.RemoveInterceptor(logger);
                    }

                    var commandsUsed = new bool[Enum.GetValues(typeof(CommandMethod)).Length];

                    for (var i = 0; i < logger.Log.Count; i++)
                    {
                        var method = logger.Log[i].Method;
                        commandsUsed[(int)method] = true;

                        if (method.ToString().EndsWith("Executing"))
                        {
                            Assert.Equal(method + 1, logger.Log[i + 1].Method);
                            Assert.Same(logger.Log[i].Command, logger.Log[i + 1].Command);
                        }
                    }

                    // Check that expected command have log entries
                    Assert.True(commandsUsed[(int)CommandMethod.ReaderExecuting]);
                    Assert.True(commandsUsed[(int)CommandMethod.ReaderExecuted]);
                    Assert.True(commandsUsed[(int)CommandMethod.ReaderExecuting]);
                    Assert.True(commandsUsed[(int)CommandMethod.ReaderExecuted]);
#if !NET40
                    Assert.True(commandsUsed[(int)CommandMethod.NonQueryExecuting]);
                    Assert.True(commandsUsed[(int)CommandMethod.NonQueryExecuted]);
#endif

                    // Sanity check on command text
                    var commandTexts = logger.Log.Select(l => l.CommandText.ToLowerInvariant());
                    Assert.True(commandTexts.Any(c => c.StartsWith("select")));
                    Assert.True(commandTexts.Any(c => c.StartsWith("insert")));
#if !NET40
                    Assert.True(commandTexts.Any(c => c.StartsWith("update")));
#endif

                    // Sanity check on results
                    Assert.True(logger.Log.Where(l => l.Method == CommandMethod.NonQueryExecuted).All(l => l.Result != null));
                    Assert.True(logger.Log.Where(l => l.Method == CommandMethod.ReaderExecuted).All(l => l.Result != null));
                }
            }, executionCount);

            // Check that each execution logged exactly the same commands.

            Assert.Equal(executionCount, loggers.Count);

            var firstLog = loggers.First().Log;
            foreach (var log in loggers.Select(l => l.Log).Skip(1))
            {
                Assert.Equal(firstLog.Count, log.Count);

                for (var i = 0; i < log.Count; i++)
                {
                    Assert.Equal(firstLog[i].Method, log[i].Method);
                    Assert.Equal(firstLog[i].CommandText, log[i].CommandText);

                    if (firstLog[i].Result == null)
                    {
                        Assert.Null(log[i].Result);
                    }
                    else
                    {
                        Assert.Same(firstLog[i].Result.GetType(), log[i].Result.GetType());
                    }
                }
            }
        }