// GET: Captain
        public ActionResult Index()
        {
            Dictionary <int, int> votes = new Dictionary <int, int>();

            //Perform a multi shard query to tally all the votes
            // Get the shards to connect to
            var shards = _shardMap.GetShards();

            // Create the multi-shard connection
            using (var conn = new MultiShardConnection(shards, Util.SqlHelper.GetCredentialsConnectionString()))
            {
                // Create a simple command
                using (MultiShardCommand cmd = conn.CreateCommand())
                {
                    // Because this query is grouped by CustomerID, which is sharded,
                    // we will not get duplicate rows.
                    cmd.CommandText = @"SELECT Captain, COUNT(*) AS Votes FROM [dbo].[Votes] GROUP BY [Captain]";

                    // Allow for partial results in case some shards do not respond in time
                    cmd.ExecutionPolicy = MultiShardExecutionPolicy.PartialResults;

                    // Allow the entire command to take up to 30 seconds
                    cmd.CommandTimeout = 30;

                    // Execute the command.
                    // We do not need to specify retry logic because MultiShardDataReader will internally retry until the CommandTimeout expires.
                    using (MultiShardDataReader reader = cmd.ExecuteReader())
                    {
                        while (reader.Read())
                        {
                            votes.Add(reader.GetInt32(0), reader.GetInt32(1));
                        }
                    }
                }
            }


            var vm = new ViewModels.Captain.IndexViewModel();

            foreach (var captain in _captainContext.Captains)
            {
                int voteCount = 0;
                votes.TryGetValue(captain.ID, out voteCount);

                vm.Captains.Add(new ViewModels.Captain.IndexViewModelCaptain()
                {
                    ID    = captain.ID,
                    Name  = captain.Name,
                    Votes = voteCount
                });
            }

            return(View(vm));
        }
        public void TestDataReaderReadException()
        {
            // Setup two data readers from shards
            var  mockReader1         = new MockSqlDataReader("Reader1");
            var  mockReader2         = new MockSqlDataReader("Reader2");
            bool movedOnToNextReader = false;
            int  invokeCount         = 1;
            Func <MockSqlDataReader, Task <bool> > ExecuteOnReadAsync = (r) =>
            {
                return(Task.Run <bool>(() =>
                {
                    // First reader throws an exception when Read
                    if (r.Name == "Reader1")
                    {
                        if (invokeCount == 2)
                        {
                            throw new InvalidOperationException();
                        }
                    }
                    else
                    {
                        movedOnToNextReader = true;
                    }
                    return true;
                }));
            };

            Action <MockSqlDataReader> ExecuteOnGetColumn = (r) =>
            {
                if (r.Name == "Reader1")
                {
                    throw new InvalidOperationException();
                }
            };

            mockReader1.ExecuteOnReadAsync = ExecuteOnReadAsync;
            mockReader1.ExecuteOnGetColumn = ExecuteOnGetColumn;
            mockReader2.ExecuteOnReadAsync = ExecuteOnReadAsync;
            var labeledDataReaders = new LabeledDbDataReader[2];

            labeledDataReaders[0] = new LabeledDbDataReader(mockReader1, new ShardLocation("test", "Shard1"),
                                                            new MockSqlCommand()
            {
                Connection = new MockSqlConnection("", () => { })
            });
            labeledDataReaders[1] = new LabeledDbDataReader(mockReader2, new ShardLocation("test", "Shard2"),
                                                            new MockSqlCommand()
            {
                Connection = new MockSqlConnection("", () => { })
            });

            // Create the MultiShardDataReader
            var mockMultiShardCmd    = MultiShardCommand.Create(null, "test");
            var multiShardDataReader = new MultiShardDataReader(mockMultiShardCmd, labeledDataReaders,
                                                                MultiShardExecutionPolicy.PartialResults, false);

            // Validate that if an exception is thrown when reading a column,
            // it is propagated back to the user
            try
            {
                multiShardDataReader.Read();
                invokeCount++;
                multiShardDataReader.GetInt32(0);
            }
            catch (Exception ex)
            {
                Assert.IsTrue(ex is InvalidOperationException, "Expected InvalidOperationException!");
            }

            // Validate that we didn't automatically move on to the next reader when we
            // hit an exception whilst reading the column and that
            // an exception from a second Read() call is stored and the reader is closed
            multiShardDataReader.Read();
            Assert.AreEqual(multiShardDataReader.MultiShardExceptions.Count, 1, "Expected exception to be recorded");
            Assert.IsTrue(mockReader1.IsClosed, "Expected reader to be closed!");

            // Validate we immediately moved on to the next reader
            multiShardDataReader.Read();
            Assert.IsTrue(movedOnToNextReader, "Should've moved on to next reader");
        }