public void SubsequentCreatesInSessionFactoryDoNotIncrementGeneratorUntilBlockSizeReached()
        {
            ResetDatabase();

            var sessionFactory = new ConfigurationFactory().CreateConfiguration().BuildSessionFactory();
            const long blockSize = 2;

            // First entity save

            var person = new PersonWithBlockSizeTwo { FirstName = "Tim", LastName = "Howard" };
            SavePersonInNewSession(sessionFactory, person);

            // After first insert the generator should be incremented
            Assert.Equal(1, person.Id);
            Assert.Equal(1 + blockSize, GetCurrentGeneratorValue(sessionFactory));

            // Second entity save

            person = new PersonWithBlockSizeTwo { FirstName = "Lionel", LastName = "Messi" };
            SavePersonInNewSession(sessionFactory, person);

            // After second insert the generator should not be incremented
            Assert.Equal(2, person.Id);
            Assert.Equal(1 + blockSize, GetCurrentGeneratorValue(sessionFactory));

            // Third entity save

            person = new PersonWithBlockSizeTwo { FirstName = "Wayne", LastName = "Rooney" };
            SavePersonInNewSession(sessionFactory, person);

            // After third insert the generator should be incremented again
            Assert.Equal(3, person.Id);
            Assert.Equal(1 + (blockSize * 2), GetCurrentGeneratorValue(sessionFactory));
        }
        public void InterleavedEntitiesWithDifferentBlockSizes()
        {
            ResetDatabase();

            var sessionFactory = new ConfigurationFactory().CreateConfiguration().BuildSessionFactory();
            const long smallBlockSize = 2;
            const long defaultBlockSize = Int16.MaxValue;

            long expectedDatabaseGeneratorValue = 1;
            Assert.Equal(expectedDatabaseGeneratorValue, GetCurrentGeneratorValue(sessionFactory));

            // ** First save of entity with small block size

            var personWithSmallBlockSize = new PersonWithBlockSizeTwo { FirstName = "Tim", LastName = "Howard" };
            SavePersonInNewSession(sessionFactory, personWithSmallBlockSize);

            // Generator should be incremented by the small block size
            long expectedSmallBlockSizeGeneratorValue = expectedDatabaseGeneratorValue;
            expectedDatabaseGeneratorValue += smallBlockSize;
            Assert.Equal(expectedSmallBlockSizeGeneratorValue, personWithSmallBlockSize.Id);
            Assert.Equal(expectedDatabaseGeneratorValue, GetCurrentGeneratorValue(sessionFactory));

            // ** First save of entity with default block size

            var personWithDefaultBlockSize = new PersonWithBlockSizeDefault { FirstName = "Tim", LastName = "Howard" };
            SavePersonInNewSession(sessionFactory, personWithDefaultBlockSize);

            // This entity should be allocated a default block
            // Database Generator should be incremented by default block size
            long expectedDefaultBlockSizeGeneratorValue = expectedDatabaseGeneratorValue;
            expectedDatabaseGeneratorValue += defaultBlockSize;
            Assert.Equal(expectedDefaultBlockSizeGeneratorValue, personWithDefaultBlockSize.Id);
            Assert.Equal(expectedDatabaseGeneratorValue, GetCurrentGeneratorValue(sessionFactory));

            // ** Second save of entity with small block size

            personWithSmallBlockSize = new PersonWithBlockSizeTwo { FirstName = "Lionel", LastName = "Messi" };
            SavePersonInNewSession(sessionFactory, personWithSmallBlockSize);

            // Database Generator should not be incremented
            expectedSmallBlockSizeGeneratorValue++;
            Assert.Equal(expectedSmallBlockSizeGeneratorValue, personWithSmallBlockSize.Id);
            Assert.Equal(expectedDatabaseGeneratorValue, GetCurrentGeneratorValue(sessionFactory));

            // ** Second save of entity with default block size

            personWithDefaultBlockSize = new PersonWithBlockSizeDefault { FirstName = "Tim", LastName = "Howard" };
            SavePersonInNewSession(sessionFactory, personWithDefaultBlockSize);

            // Database Generator should not be incremented
            expectedDefaultBlockSizeGeneratorValue++;
            Assert.Equal(expectedDefaultBlockSizeGeneratorValue, personWithDefaultBlockSize.Id);
            Assert.Equal(expectedDatabaseGeneratorValue, GetCurrentGeneratorValue(sessionFactory));

            // Third save of entity with small block size

            personWithSmallBlockSize = new PersonWithBlockSizeTwo { FirstName = "Wayne", LastName = "Rooney" };
            SavePersonInNewSession(sessionFactory, personWithSmallBlockSize);

            // Database Generator should be incremented again
            expectedSmallBlockSizeGeneratorValue = expectedDatabaseGeneratorValue;
            expectedDatabaseGeneratorValue += smallBlockSize;
            Assert.Equal(expectedSmallBlockSizeGeneratorValue, personWithSmallBlockSize.Id);
            Assert.Equal(expectedDatabaseGeneratorValue, GetCurrentGeneratorValue(sessionFactory));
        }
        public void GeneratorIsInitializedToZeroWithBlockSizeTwo()
        {
            ResetDatabase();

            // Note: zero should be skipped as an ID to conform to expected NHibernate behavior

            var sessionFactory = new ConfigurationFactory().CreateConfiguration().BuildSessionFactory();
            const long smallBlockSize = 2;

            // Set generator to zero
            using (var session = sessionFactory.OpenSession())
            using (var tx = session.BeginTransaction())
            {
                var sqlQuery = session.CreateSQLQuery("UPDATE hibernate_unique_key SET next_id = 0");
                sqlQuery.ExecuteUpdate();
                tx.Commit();
            }
            Assert.Equal(0, GetCurrentGeneratorValue(sessionFactory));

            // ** First save of entity should get ID 1 (generator incremented)
            var personWithSmallBlockSize = new PersonWithBlockSizeTwo { FirstName = "Tim", LastName = "Howard" };
            SavePersonInNewSession(sessionFactory, personWithSmallBlockSize);
            Assert.Equal(1, personWithSmallBlockSize.Id);
            Assert.Equal(smallBlockSize, GetCurrentGeneratorValue(sessionFactory));

            // ** Second save of entity should get ID 2 (generator incremented)
            personWithSmallBlockSize = new PersonWithBlockSizeTwo { FirstName = "Tim", LastName = "Howard" };
            SavePersonInNewSession(sessionFactory, personWithSmallBlockSize);
            Assert.Equal(2, personWithSmallBlockSize.Id);
            Assert.Equal(smallBlockSize * 2, GetCurrentGeneratorValue(sessionFactory));

            // ** Third save of entity should get ID 3 (generator not incremented)
            personWithSmallBlockSize = new PersonWithBlockSizeTwo { FirstName = "Tim", LastName = "Howard" };
            SavePersonInNewSession(sessionFactory, personWithSmallBlockSize);
            Assert.Equal(3, personWithSmallBlockSize.Id);
            Assert.Equal(smallBlockSize * 2, GetCurrentGeneratorValue(sessionFactory));

            // ** Fourth save of entity should get ID 4 (generator incremented)
            personWithSmallBlockSize = new PersonWithBlockSizeTwo { FirstName = "Tim", LastName = "Howard" };
            SavePersonInNewSession(sessionFactory, personWithSmallBlockSize);
            Assert.Equal(4, personWithSmallBlockSize.Id);
            Assert.Equal(smallBlockSize * 3, GetCurrentGeneratorValue(sessionFactory));
        }