public void Performance_Identities_Stored_In_The_Database_Concurrent_Access()
        {
            ManualResetEventSlim ev       = new ManualResetEventSlim(false);
            Object readSynchronization    = new object();
            Object writeSynchronization   = new object();
            Object processSynchronization = new object();
            long   ms1 = 0;
            long   ms  = 0;

            Action a = new Action(() =>
            {
                using (Levels context = new Levels())
                {
                    ev.Wait();
                    Test_Identities_Stored_In_The_Database(t => ms1 += t, readSynchronization, writeSynchronization, processSynchronization);
                    Trace.WriteLine(string.Format("[Thread {0}]: elapsed {1}", Thread.CurrentThread.ManagedThreadId.ToString(), (ms1 / 1000.00).ToString()));
                }
            });

            const int NUM_TASKS = 20;

            using (new MetricTracker("Starting multiple threads", t => ms += t))
            {
                List <Task> tasks = new List <Task>();
                for (int i = 0; i < NUM_TASKS; i++)
                {
                    tasks.Add(new TaskFactory().StartNew(a));
                }
                ev.Set();

                Task.WaitAll(tasks.ToArray());
            }

            Console.WriteLine("Elapsed: {0}", (ms1 / 1000.00).ToString());
            ms1.Should().BeLessThan(17900);

            using (Levels context = new Levels())
            {
                LevelIdentityFactory ids = new LevelIdentityFactory(readSynchronization, writeSynchronization, processSynchronization);
                ids.ReadFromDatabase(context);
                ids.Identities["Level1"].Should().Be(NUM_TASKS + 1);        // + "A"
                ids.Identities["Level2"].Should().Be(NUM_TASKS * 5 + 1);    // + 1 extra number per each insert
                ids.Identities["Level3"].Should().Be(NUM_TASKS * 25 + 1);   // + 1 extra number per each insert
                ids.Identities["Level4"].Should().Be(NUM_TASKS * 250 + 1);  // + 1 extra number per each insert
                ids.Identities["Level5"].Should().Be(NUM_TASKS * 2500 + 1); // + 1 extra number per each insert
            }
        }
        private void Test_Identities_Stored_In_The_Database(Action <long> ms, Object ReadSynchronization, Object WriteSynchronization, Object ProcessSynchronization)
        {
            LevelIdentityFactory ids = new LevelIdentityFactory(ReadSynchronization, WriteSynchronization, ProcessSynchronization);

            using (Levels context = new Levels())
                using (new MetricTracker("Starting complex object", ms))
                {
                    ObjectContext o = ((IObjectContextAdapter)context).ObjectContext;
                    o.Connection.Open();
                    try
                    {
                        // Unprotected object creation and work.
                        Level1 level1 = GetSample();

                        using (TransactionScope tran = new TransactionScope(
                                   TransactionScopeOption.RequiresNew,
                                   new TransactionOptions {
                            IsolationLevel = IsolationLevel.Serializable
                        }))
                        {
                            // Protected identification set read.
                            ids.ReadFromDatabase(context);

                            // Protected Id assignment.
                            ids.AssignIdentities(level1);

                            // Protected object save.
                            context.Level1.Add(level1);
                            context.SaveChanges();

                            // Protected new Id values write.
                            ids.WriteToDatabase(context);

                            // Completion
                            tran.Complete();
                        }
                    }
                    finally
                    {
                        o.Connection.Close();
                    }
                }
        }
        public void Performance_Identities_Stored_In_The_Database()
        {
            long   ms = 0;
            Object readSynchronization    = new object();
            Object writeSynchronization   = new object();
            Object processSynchronization = new object();

            Test_Identities_Stored_In_The_Database(t => ms = t, readSynchronization, writeSynchronization, processSynchronization);
            ms.Should().BeLessThan(1440);

            using (Levels context = new Levels())
            {
                LevelIdentityFactory ids = new LevelIdentityFactory(readSynchronization, writeSynchronization, processSynchronization);
                ids.ReadFromDatabase(context);
                ids.Identities["Level1"].Should().Be(2);        // + "A"
                ids.Identities["Level2"].Should().Be(6);        // + 1 extra number per each insert
                ids.Identities["Level3"].Should().Be(26);       // + 1 extra number per each insert
                ids.Identities["Level4"].Should().Be(251);      // + 1 extra number per each insert
                ids.Identities["Level5"].Should().Be(2501);     // + 1 extra number per each insert
            }
        }