/// <summary>
        /// Executes the Multi-Shard Query sample.
        /// </summary>
        private static void MultiShardQuery()
        {
            RangeShardMap <int> shardMap = MultiShardConfiguration.TryGetShardMap();

            if (shardMap != null)
            {
                MultiShardQuerySupport.ExecuteMultiShardQuery(shardMap);
            }
        }
        /// <summary>
        /// Executes the Data-Dependent Routing sample.
        /// </summary>
        private static void DataDepdendentRoutingForDelete()
        {
            RangeShardMap <int> shardMap = MultiShardConfiguration.TryGetShardMap();

            if (shardMap != null)
            {
                DataDependentRoutingSupport.ExecuteDataDependentRoutingQueryForDelete(shardMap);
            }
        }
        /// <summary>
        /// Writes the shard map's state to the console.
        /// </summary>
        private static void PrintShardMapState()
        {
            Console.WriteLine("Current Shard Map state:");
            RangeShardMap <int> shardMap = MultiShardConfiguration.TryGetShardMap();

            if (shardMap == null)
            {
                return;
            }

            // Get all shards
            IEnumerable <Shard> allShards = shardMap.GetShards();

            // Get all mappings, grouped by the shard that they are on. We do this all in one go to minimise round trips.
            ILookup <Shard, RangeMapping <int> > mappingsGroupedByShard = shardMap.GetMappings().ToLookup(m => m.Shard);

            if (allShards.Any())
            {
                // The shard map contains some shards, so for each shard (sorted by database name)
                // write out the mappings for that shard
                foreach (Shard shard in shardMap.GetShards().OrderBy(s => s.Location.Database))
                {
                    IEnumerable <RangeMapping <int> > mappingsOnThisShard = mappingsGroupedByShard[shard];

                    if (mappingsOnThisShard.Any())
                    {
                        string mappingsString = string.Join(", ", mappingsOnThisShard.Select(m => m.Value));
                        Console.WriteLine("\t{0} contains key range {1}", shard.Location.Database, mappingsString);
                    }
                    else
                    {
                        Console.WriteLine("\t{0} contains no key ranges.", shard.Location.Database);
                    }
                }
            }
            else
            {
                Console.WriteLine("\tShard Map contains no shards");
            }
        }
        /// <summary>
        /// Drops all shards and the shard map manager database (if it exists).
        /// </summary>
        private static void DropAll()
        {
            RangeShardMap <int> shardMap = MultiShardConfiguration.TryGetShardMap();

            if (shardMap != null)
            {
                // Drop shards
                foreach (Shard shard in shardMap.GetShards())
                {
                    SqlDatabaseUtils.DropDatabase(shard.Location.DataSource, shard.Location.Database);
                }
            }

            if (SqlDatabaseUtils.ExistsDatabase(MultiShardConfiguration.ShardMapManagerServerName, MultiShardConfiguration.ShardMapManagerDatabaseName))
            {
                // Drop shard map manager database
                SqlDatabaseUtils.DropDatabase(MultiShardConfiguration.ShardMapManagerServerName, MultiShardConfiguration.ShardMapManagerDatabaseName);
            }

            // Since we just dropped the shard map manager database, this shardMapManager reference is now non-functional.
            // So set it to null so that the program knows that the shard map manager is gone.
            MultiShardConfiguration.objShardMapManager = null;
        }
        /// <summary>
        /// Reads the user's choice of a split point, and creates a new shard with a mapping for the resulting range.
        /// </summary>
        private static void AddShard()
        {
            RangeShardMap <int> shardMap = MultiShardConfiguration.TryGetShardMap();

            if (shardMap != null)
            {
                // Here we assume that the ranges start at 0, are contiguous,
                // and are bounded (i.e. there is no range where HighIsMax == true)
                int currentMaxHighKey = shardMap.GetMappings().Max(m => m.Value.High);
                int defaultNewHighKey = currentMaxHighKey + 100;

                Console.WriteLine("A new range with low key {0} will be mapped to the new shard.", currentMaxHighKey);
                int newHighKey = ConsoleUtils.ReadIntegerInput(
                    string.Format("Enter the high key for the new range [default {0}]: ", defaultNewHighKey),
                    defaultNewHighKey,
                    input => input > currentMaxHighKey);

                Range <int> range = new Range <int>(currentMaxHighKey, newHighKey);

                Console.WriteLine();
                Console.WriteLine("Creating shard for range {0}", range);
                CreateShardSample.CreateShard(shardMap, range);
            }
        }